144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2230ac2e7bSml * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish /* 2944961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 3044961713Sgirish */ 3144961713Sgirish #include <sys/nxge/nxge_impl.h> 32678453a8Sspeer #include <sys/nxge/nxge_hio.h> 33678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 3414ea4bb7Ssd #include <sys/pcie.h> 3544961713Sgirish 3644961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3744961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3844961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3944961713Sgirish /* 40ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 41ec090658Sml * (This PSARC case is limited to MSI-X vectors 42ec090658Sml * and SPARC platforms only). 4344961713Sgirish */ 44ec090658Sml #if defined(_BIG_ENDIAN) 45ec090658Sml uint32_t nxge_msi_enable = 2; 46ec090658Sml #else 47ec090658Sml uint32_t nxge_msi_enable = 1; 48ec090658Sml #endif 4944961713Sgirish 50*6f157acbSml /* 51*6f157acbSml * Software workaround for a Neptune (PCI-E) 52*6f157acbSml * hardware interrupt bug which the hardware 53*6f157acbSml * may generate spurious interrupts after the 54*6f157acbSml * device interrupt handler was removed. If this flag 55*6f157acbSml * is enabled, the driver will reset the 56*6f157acbSml * hardware when devices are being detached. 57*6f157acbSml */ 58*6f157acbSml uint32_t nxge_peu_reset_enable = 0; 59*6f157acbSml 60b4d05839Sml /* 61b4d05839Sml * Software workaround for the hardware 62b4d05839Sml * checksum bugs that affect packet transmission 63b4d05839Sml * and receive: 64b4d05839Sml * 65b4d05839Sml * Usage of nxge_cksum_offload: 66b4d05839Sml * 67b4d05839Sml * (1) nxge_cksum_offload = 0 (default): 68b4d05839Sml * - transmits packets: 69b4d05839Sml * TCP: uses the hardware checksum feature. 70b4d05839Sml * UDP: driver will compute the software checksum 71b4d05839Sml * based on the partial checksum computed 72b4d05839Sml * by the IP layer. 73b4d05839Sml * - receives packets 74b4d05839Sml * TCP: marks packets checksum flags based on hardware result. 75b4d05839Sml * UDP: will not mark checksum flags. 76b4d05839Sml * 77b4d05839Sml * (2) nxge_cksum_offload = 1: 78b4d05839Sml * - transmit packets: 79b4d05839Sml * TCP/UDP: uses the hardware checksum feature. 80b4d05839Sml * - receives packets 81b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result. 82b4d05839Sml * 83b4d05839Sml * (3) nxge_cksum_offload = 2: 84b4d05839Sml * - The driver will not register its checksum capability. 85b4d05839Sml * Checksum for both TCP and UDP will be computed 86b4d05839Sml * by the stack. 87b4d05839Sml * - The software LSO is not allowed in this case. 88b4d05839Sml * 89b4d05839Sml * (4) nxge_cksum_offload > 2: 90b4d05839Sml * - Will be treated as it is set to 2 91b4d05839Sml * (stack will compute the checksum). 92b4d05839Sml * 93b4d05839Sml * (5) If the hardware bug is fixed, this workaround 94b4d05839Sml * needs to be updated accordingly to reflect 95b4d05839Sml * the new hardware revision. 96b4d05839Sml */ 97b4d05839Sml uint32_t nxge_cksum_offload = 0; 98678453a8Sspeer 9944961713Sgirish /* 10044961713Sgirish * Globals: tunable parameters (/etc/system or adb) 10144961713Sgirish * 10244961713Sgirish */ 10344961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 10444961713Sgirish uint32_t nxge_rbr_spare_size = 0; 10544961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 10644961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 107b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 10844961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 10944961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 11044961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 11144961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 11244961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 11344961713Sgirish boolean_t nxge_jumbo_enable = B_FALSE; 11444961713Sgirish uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT; 11544961713Sgirish uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD; 1161f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 11744961713Sgirish 11830ac2e7bSml /* MAX LSO size */ 11930ac2e7bSml #define NXGE_LSO_MAXLEN 65535 12030ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 12130ac2e7bSml 12244961713Sgirish /* 12344961713Sgirish * Debugging flags: 12444961713Sgirish * nxge_no_tx_lb : transmit load balancing 12544961713Sgirish * nxge_tx_lb_policy: 0 - TCP port (default) 12644961713Sgirish * 3 - DEST MAC 12744961713Sgirish */ 12844961713Sgirish uint32_t nxge_no_tx_lb = 0; 12944961713Sgirish uint32_t nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP; 13044961713Sgirish 13144961713Sgirish /* 13244961713Sgirish * Add tunable to reduce the amount of time spent in the 13344961713Sgirish * ISR doing Rx Processing. 13444961713Sgirish */ 13544961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 13644961713Sgirish 13744961713Sgirish /* 13844961713Sgirish * Tunables to manage the receive buffer blocks. 13944961713Sgirish * 14044961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 14144961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 14244961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 14344961713Sgirish */ 14444961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 14544961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 14644961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 14744961713Sgirish 148678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 149678453a8Sspeer #if !defined(__i386) 150d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 151678453a8Sspeer #else 152d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 153678453a8Sspeer #endif 154678453a8Sspeer 15544961713Sgirish rtrace_t npi_rtracebuf; 15644961713Sgirish 15744961713Sgirish #if defined(sun4v) 15844961713Sgirish /* 15944961713Sgirish * Hypervisor N2/NIU services information. 16044961713Sgirish */ 16144961713Sgirish static hsvc_info_t niu_hsvc = { 16244961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 16344961713Sgirish NIU_MINOR_VER, "nxge" 16444961713Sgirish }; 165678453a8Sspeer 166678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 16744961713Sgirish #endif 16844961713Sgirish 16944961713Sgirish /* 17044961713Sgirish * Function Prototypes 17144961713Sgirish */ 17244961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 17344961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 17444961713Sgirish static void nxge_unattach(p_nxge_t); 17544961713Sgirish 17644961713Sgirish #if NXGE_PROPERTY 17744961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 17844961713Sgirish #endif 17944961713Sgirish 180678453a8Sspeer /* 181678453a8Sspeer * These two functions are required by nxge_hio.c 182678453a8Sspeer */ 183678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 184678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 185678453a8Sspeer 18644961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 18744961713Sgirish 18844961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 18944961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 19044961713Sgirish 19144961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 19244961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 19344961713Sgirish #ifdef NXGE_DEBUG 19444961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 19544961713Sgirish #endif 19644961713Sgirish 19744961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 19844961713Sgirish static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep); 19944961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 20044961713Sgirish static void nxge_remove_soft_intrs(p_nxge_t nxgep); 20144961713Sgirish 20244961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 20344961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 20444961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 20544961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 20644961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 20744961713Sgirish 20844961713Sgirish static void nxge_suspend(p_nxge_t); 20944961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 21044961713Sgirish 21144961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 21244961713Sgirish static void nxge_destroy_dev(p_nxge_t); 21344961713Sgirish 21444961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 21544961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 21644961713Sgirish 217678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 21844961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 21944961713Sgirish 220678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 22144961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 22244961713Sgirish 22344961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 22444961713Sgirish struct ddi_dma_attr *, 22544961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 22644961713Sgirish p_nxge_dma_common_t); 22744961713Sgirish 22844961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 229678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 23044961713Sgirish 23144961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 23244961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 23344961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 23444961713Sgirish 23544961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 23644961713Sgirish p_nxge_dma_common_t *, size_t); 23744961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 23844961713Sgirish 239678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 24044961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 24144961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 24244961713Sgirish 243678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 24444961713Sgirish p_nxge_dma_common_t *, 24544961713Sgirish size_t); 24644961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 24744961713Sgirish 24844961713Sgirish static int nxge_init_common_dev(p_nxge_t); 24944961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2504045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2514045d941Ssowmini char *, caddr_t); 25244961713Sgirish 25344961713Sgirish /* 25444961713Sgirish * The next declarations are for the GLDv3 interface. 25544961713Sgirish */ 25644961713Sgirish static int nxge_m_start(void *); 25744961713Sgirish static void nxge_m_stop(void *); 25844961713Sgirish static int nxge_m_unicst(void *, const uint8_t *); 25944961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 26044961713Sgirish static int nxge_m_promisc(void *, boolean_t); 26144961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 26244961713Sgirish static void nxge_m_resources(void *); 26344961713Sgirish mblk_t *nxge_m_tx(void *arg, mblk_t *); 26444961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t); 26558324dfcSspeer static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 26658324dfcSspeer mac_addr_slot_t slot); 267678453a8Sspeer void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 26858324dfcSspeer boolean_t factory); 26958324dfcSspeer static int nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr); 27058324dfcSspeer static int nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 27158324dfcSspeer static int nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 2721bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2731bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2741bd6825cSml uint_t, const void *); 2751bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 2764045d941Ssowmini uint_t, uint_t, void *); 2771bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 2781bd6825cSml const void *); 2794045d941Ssowmini static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, uint_t, 2801bd6825cSml void *); 2814045d941Ssowmini static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); 2824045d941Ssowmini 283*6f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 2844045d941Ssowmini 2854045d941Ssowmini mac_priv_prop_t nxge_priv_props[] = { 2864045d941Ssowmini {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, 2874045d941Ssowmini {"_adv_pause_cap", MAC_PROP_PERM_RW}, 2884045d941Ssowmini {"_function_number", MAC_PROP_PERM_READ}, 2894045d941Ssowmini {"_fw_version", MAC_PROP_PERM_READ}, 2904045d941Ssowmini {"_port_mode", MAC_PROP_PERM_READ}, 2914045d941Ssowmini {"_hot_swap_phy", MAC_PROP_PERM_READ}, 2924045d941Ssowmini {"_accept_jumbo", MAC_PROP_PERM_RW}, 2934045d941Ssowmini {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 2944045d941Ssowmini {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 2954045d941Ssowmini {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 2964045d941Ssowmini {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 2974045d941Ssowmini {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 2984045d941Ssowmini {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 2994045d941Ssowmini {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 3004045d941Ssowmini {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 3014045d941Ssowmini {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 3024045d941Ssowmini {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}, 3034045d941Ssowmini {"_soft_lso_enable", MAC_PROP_PERM_RW} 3044045d941Ssowmini }; 3054045d941Ssowmini 3064045d941Ssowmini #define NXGE_MAX_PRIV_PROPS \ 3074045d941Ssowmini (sizeof (nxge_priv_props)/sizeof (mac_priv_prop_t)) 3081bd6825cSml 3091bd6825cSml #define NXGE_M_CALLBACK_FLAGS\ 3101bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 3111bd6825cSml 31244961713Sgirish 31344961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 31444961713Sgirish #define MAX_DUMP_SZ 256 31544961713Sgirish 3161bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 3171bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 31844961713Sgirish 319678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 32044961713Sgirish NXGE_M_CALLBACK_FLAGS, 32144961713Sgirish nxge_m_stat, 32244961713Sgirish nxge_m_start, 32344961713Sgirish nxge_m_stop, 32444961713Sgirish nxge_m_promisc, 32544961713Sgirish nxge_m_multicst, 32644961713Sgirish nxge_m_unicst, 32744961713Sgirish nxge_m_tx, 32844961713Sgirish nxge_m_resources, 32944961713Sgirish nxge_m_ioctl, 3301bd6825cSml nxge_m_getcapab, 3311bd6825cSml NULL, 3321bd6825cSml NULL, 3331bd6825cSml nxge_m_setprop, 3341bd6825cSml nxge_m_getprop 33544961713Sgirish }; 33644961713Sgirish 33744961713Sgirish void 33844961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 33944961713Sgirish 340ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 341ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 342ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 343ec090658Sml static int nxge_create_msi_property(p_nxge_t); 344ec090658Sml 34544961713Sgirish /* 34644961713Sgirish * These global variables control the message 34744961713Sgirish * output. 34844961713Sgirish */ 34944961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 350678453a8Sspeer uint64_t nxge_debug_level; 35144961713Sgirish 35244961713Sgirish /* 35344961713Sgirish * This list contains the instance structures for the Neptune 35444961713Sgirish * devices present in the system. The lock exists to guarantee 35544961713Sgirish * mutually exclusive access to the list. 35644961713Sgirish */ 35744961713Sgirish void *nxge_list = NULL; 35844961713Sgirish 35944961713Sgirish void *nxge_hw_list = NULL; 36044961713Sgirish nxge_os_mutex_t nxge_common_lock; 36144961713Sgirish 36244961713Sgirish extern uint64_t npi_debug_level; 36344961713Sgirish 36444961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 36544961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 36644961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 36744961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 36844961713Sgirish extern void nxge_fm_init(p_nxge_t, 36944961713Sgirish ddi_device_acc_attr_t *, 37044961713Sgirish ddi_device_acc_attr_t *, 37144961713Sgirish ddi_dma_attr_t *); 37244961713Sgirish extern void nxge_fm_fini(p_nxge_t); 37358324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 37444961713Sgirish 37544961713Sgirish /* 37644961713Sgirish * Count used to maintain the number of buffers being used 37744961713Sgirish * by Neptune instances and loaned up to the upper layers. 37844961713Sgirish */ 37944961713Sgirish uint32_t nxge_mblks_pending = 0; 38044961713Sgirish 38144961713Sgirish /* 38244961713Sgirish * Device register access attributes for PIO. 38344961713Sgirish */ 38444961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 38544961713Sgirish DDI_DEVICE_ATTR_V0, 38644961713Sgirish DDI_STRUCTURE_LE_ACC, 38744961713Sgirish DDI_STRICTORDER_ACC, 38844961713Sgirish }; 38944961713Sgirish 39044961713Sgirish /* 39144961713Sgirish * Device descriptor access attributes for DMA. 39244961713Sgirish */ 39344961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 39444961713Sgirish DDI_DEVICE_ATTR_V0, 39544961713Sgirish DDI_STRUCTURE_LE_ACC, 39644961713Sgirish DDI_STRICTORDER_ACC 39744961713Sgirish }; 39844961713Sgirish 39944961713Sgirish /* 40044961713Sgirish * Device buffer access attributes for DMA. 40144961713Sgirish */ 40244961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 40344961713Sgirish DDI_DEVICE_ATTR_V0, 40444961713Sgirish DDI_STRUCTURE_BE_ACC, 40544961713Sgirish DDI_STRICTORDER_ACC 40644961713Sgirish }; 40744961713Sgirish 40844961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 40944961713Sgirish DMA_ATTR_V0, /* version number. */ 41044961713Sgirish 0, /* low address */ 41144961713Sgirish 0xffffffffffffffff, /* high address */ 41244961713Sgirish 0xffffffffffffffff, /* address counter max */ 41344961713Sgirish #ifndef NIU_PA_WORKAROUND 41444961713Sgirish 0x100000, /* alignment */ 41544961713Sgirish #else 41644961713Sgirish 0x2000, 41744961713Sgirish #endif 41844961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 41944961713Sgirish 0x1, /* minimum transfer size */ 42044961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 42144961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 42244961713Sgirish 1, /* scatter/gather list length */ 42344961713Sgirish (unsigned int) 1, /* granularity */ 42444961713Sgirish 0 /* attribute flags */ 42544961713Sgirish }; 42644961713Sgirish 42744961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 42844961713Sgirish DMA_ATTR_V0, /* version number. */ 42944961713Sgirish 0, /* low address */ 43044961713Sgirish 0xffffffffffffffff, /* high address */ 43144961713Sgirish 0xffffffffffffffff, /* address counter max */ 43244961713Sgirish #if defined(_BIG_ENDIAN) 43344961713Sgirish 0x2000, /* alignment */ 43444961713Sgirish #else 43544961713Sgirish 0x1000, /* alignment */ 43644961713Sgirish #endif 43744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 43844961713Sgirish 0x1, /* minimum transfer size */ 43944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 44044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 44144961713Sgirish 5, /* scatter/gather list length */ 44244961713Sgirish (unsigned int) 1, /* granularity */ 44344961713Sgirish 0 /* attribute flags */ 44444961713Sgirish }; 44544961713Sgirish 44644961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 44744961713Sgirish DMA_ATTR_V0, /* version number. */ 44844961713Sgirish 0, /* low address */ 44944961713Sgirish 0xffffffffffffffff, /* high address */ 45044961713Sgirish 0xffffffffffffffff, /* address counter max */ 45144961713Sgirish 0x2000, /* alignment */ 45244961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 45344961713Sgirish 0x1, /* minimum transfer size */ 45444961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 45544961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 45644961713Sgirish 1, /* scatter/gather list length */ 45744961713Sgirish (unsigned int) 1, /* granularity */ 4580e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 45944961713Sgirish }; 46044961713Sgirish 46144961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 46244961713Sgirish (uint_t)0, /* dlim_addr_lo */ 46344961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 46444961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 46544961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 46644961713Sgirish 0x1, /* dlim_minxfer */ 46744961713Sgirish 1024 /* dlim_speed */ 46844961713Sgirish }; 46944961713Sgirish 47044961713Sgirish dma_method_t nxge_force_dma = DVMA; 47144961713Sgirish 47244961713Sgirish /* 47344961713Sgirish * dma chunk sizes. 47444961713Sgirish * 47544961713Sgirish * Try to allocate the largest possible size 47644961713Sgirish * so that fewer number of dma chunks would be managed 47744961713Sgirish */ 47844961713Sgirish #ifdef NIU_PA_WORKAROUND 47944961713Sgirish size_t alloc_sizes [] = {0x2000}; 48044961713Sgirish #else 48144961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 48244961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 48330ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 48430ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 48544961713Sgirish #endif 48644961713Sgirish 48744961713Sgirish /* 48844961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 48944961713Sgirish */ 49044961713Sgirish 491678453a8Sspeer extern void nxge_get_environs(nxge_t *); 492678453a8Sspeer 49344961713Sgirish static int 49444961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 49544961713Sgirish { 49644961713Sgirish p_nxge_t nxgep = NULL; 49744961713Sgirish int instance; 49844961713Sgirish int status = DDI_SUCCESS; 49944961713Sgirish uint8_t portn; 50058324dfcSspeer nxge_mmac_t *mmac_info; 50144961713Sgirish 50244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 50344961713Sgirish 50444961713Sgirish /* 50544961713Sgirish * Get the device instance since we'll need to setup 50644961713Sgirish * or retrieve a soft state for this instance. 50744961713Sgirish */ 50844961713Sgirish instance = ddi_get_instance(dip); 50944961713Sgirish 51044961713Sgirish switch (cmd) { 51144961713Sgirish case DDI_ATTACH: 51244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 51344961713Sgirish break; 51444961713Sgirish 51544961713Sgirish case DDI_RESUME: 51644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 51744961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 51844961713Sgirish if (nxgep == NULL) { 51944961713Sgirish status = DDI_FAILURE; 52044961713Sgirish break; 52144961713Sgirish } 52244961713Sgirish if (nxgep->dip != dip) { 52344961713Sgirish status = DDI_FAILURE; 52444961713Sgirish break; 52544961713Sgirish } 52644961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 52744961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 52844961713Sgirish } else { 52956d930aeSspeer status = nxge_resume(nxgep); 53044961713Sgirish } 53144961713Sgirish goto nxge_attach_exit; 53244961713Sgirish 53344961713Sgirish case DDI_PM_RESUME: 53444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 53544961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 53644961713Sgirish if (nxgep == NULL) { 53744961713Sgirish status = DDI_FAILURE; 53844961713Sgirish break; 53944961713Sgirish } 54044961713Sgirish if (nxgep->dip != dip) { 54144961713Sgirish status = DDI_FAILURE; 54244961713Sgirish break; 54344961713Sgirish } 54456d930aeSspeer status = nxge_resume(nxgep); 54544961713Sgirish goto nxge_attach_exit; 54644961713Sgirish 54744961713Sgirish default: 54844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 54944961713Sgirish status = DDI_FAILURE; 55044961713Sgirish goto nxge_attach_exit; 55144961713Sgirish } 55244961713Sgirish 55344961713Sgirish 55444961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 55544961713Sgirish status = DDI_FAILURE; 55644961713Sgirish goto nxge_attach_exit; 55744961713Sgirish } 55844961713Sgirish 55944961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 56044961713Sgirish if (nxgep == NULL) { 5612e59129aSraghus status = NXGE_ERROR; 5622e59129aSraghus goto nxge_attach_fail2; 56344961713Sgirish } 56444961713Sgirish 56598ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 56698ecde52Stm 56744961713Sgirish nxgep->drv_state = 0; 56844961713Sgirish nxgep->dip = dip; 56944961713Sgirish nxgep->instance = instance; 57044961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 57144961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 57244961713Sgirish npi_debug_level = nxge_debug_level; 57344961713Sgirish 574678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 575678453a8Sspeer nxge_get_environs(nxgep); 57644961713Sgirish 57744961713Sgirish status = nxge_map_regs(nxgep); 578678453a8Sspeer 57944961713Sgirish if (status != NXGE_OK) { 58044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 5812e59129aSraghus goto nxge_attach_fail3; 58244961713Sgirish } 58344961713Sgirish 584678453a8Sspeer nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, 585678453a8Sspeer &nxge_dev_desc_dma_acc_attr, 586678453a8Sspeer &nxge_rx_dma_attr); 587678453a8Sspeer 588678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 589678453a8Sspeer /* (even if we're a guest). */ 59044961713Sgirish status = nxge_init_common_dev(nxgep); 59144961713Sgirish if (status != NXGE_OK) { 59244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5934045d941Ssowmini "nxge_init_common_dev failed")); 5942e59129aSraghus goto nxge_attach_fail4; 59544961713Sgirish } 59644961713Sgirish 597678453a8Sspeer #if defined(sun4v) 598678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 599678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 600678453a8Sspeer goto nxge_attach_fail; 601678453a8Sspeer #endif 602678453a8Sspeer 603678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 604678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6054045d941Ssowmini "nxge_hio_init failed")); 606678453a8Sspeer goto nxge_attach_fail4; 607678453a8Sspeer } 608678453a8Sspeer 60959ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 61059ac0c16Sdavemq if (nxgep->function_num > 1) { 6114202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 61259ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 61359ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 61459ac0c16Sdavemq status = NXGE_ERROR; 6152e59129aSraghus goto nxge_attach_fail4; 61659ac0c16Sdavemq } 61759ac0c16Sdavemq } 61859ac0c16Sdavemq 619678453a8Sspeer if (isLDOMguest(nxgep)) { 620678453a8Sspeer /* 621678453a8Sspeer * Use the function number here. 622678453a8Sspeer */ 623678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 624678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 625678453a8Sspeer 626678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 627678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 628678453a8Sspeer mmac_info->num_mmac = 1; 629678453a8Sspeer mmac_info->naddrfree = 1; 63058324dfcSspeer } else { 631678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 632678453a8Sspeer nxgep->mac.portnum = portn; 633678453a8Sspeer if ((portn == 0) || (portn == 1)) 634678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 635678453a8Sspeer else 636678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 637678453a8Sspeer /* 638678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 639678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 640678453a8Sspeer * The two types of MACs have different characterizations. 641678453a8Sspeer */ 642678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 643678453a8Sspeer if (nxgep->function_num < 2) { 644678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 645678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 646678453a8Sspeer } else { 647678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 648678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 649678453a8Sspeer } 65058324dfcSspeer } 65144961713Sgirish /* 65244961713Sgirish * Setup the Ndd parameters for the this instance. 65344961713Sgirish */ 65444961713Sgirish nxge_init_param(nxgep); 65544961713Sgirish 65644961713Sgirish /* 65744961713Sgirish * Setup Register Tracing Buffer. 65844961713Sgirish */ 65944961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 66044961713Sgirish 66144961713Sgirish /* init stats ptr */ 66244961713Sgirish nxge_init_statsp(nxgep); 66356d930aeSspeer 6642e59129aSraghus /* 665678453a8Sspeer * Copy the vpd info from eeprom to a local data 666678453a8Sspeer * structure, and then check its validity. 6672e59129aSraghus */ 668678453a8Sspeer if (!isLDOMguest(nxgep)) { 669678453a8Sspeer int *regp; 670678453a8Sspeer uint_t reglen; 671678453a8Sspeer int rv; 67256d930aeSspeer 673678453a8Sspeer nxge_vpd_info_get(nxgep); 67444961713Sgirish 675678453a8Sspeer /* Find the NIU config handle. */ 676678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 677678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 678678453a8Sspeer "reg", ®p, ®len); 679678453a8Sspeer 680678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 681678453a8Sspeer goto nxge_attach_fail5; 682678453a8Sspeer } 683678453a8Sspeer /* 684678453a8Sspeer * The address_hi, that is the first int, in the reg 685678453a8Sspeer * property consists of config handle, but need to remove 686678453a8Sspeer * the bits 28-31 which are OBP specific info. 687678453a8Sspeer */ 688678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 689678453a8Sspeer ddi_prop_free(regp); 69044961713Sgirish } 69144961713Sgirish 692678453a8Sspeer if (isLDOMguest(nxgep)) { 693678453a8Sspeer uchar_t *prop_val; 694678453a8Sspeer uint_t prop_len; 69544961713Sgirish 696678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 697678453a8Sspeer 698678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 699678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 700678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 701678453a8Sspeer "phy-type", "virtual transceiver"); 702678453a8Sspeer 703678453a8Sspeer nxgep->nports = 1; 704678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 705678453a8Sspeer 706678453a8Sspeer /* 707678453a8Sspeer * local-mac-address property gives us info on which 708678453a8Sspeer * specific MAC address the Hybrid resource is associated 709678453a8Sspeer * with. 710678453a8Sspeer */ 711678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 712678453a8Sspeer "local-mac-address", &prop_val, 713678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 714678453a8Sspeer goto nxge_attach_fail5; 715678453a8Sspeer } 716678453a8Sspeer if (prop_len != ETHERADDRL) { 717678453a8Sspeer ddi_prop_free(prop_val); 718678453a8Sspeer goto nxge_attach_fail5; 719678453a8Sspeer } 720678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 721678453a8Sspeer ddi_prop_free(prop_val); 722678453a8Sspeer nxge_get_logical_props(nxgep); 723678453a8Sspeer 724678453a8Sspeer } else { 725678453a8Sspeer status = nxge_xcvr_find(nxgep); 726678453a8Sspeer 727678453a8Sspeer if (status != NXGE_OK) { 728678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7294045d941Ssowmini " Couldn't determine card type" 7304045d941Ssowmini " .... exit ")); 731678453a8Sspeer goto nxge_attach_fail5; 732678453a8Sspeer } 733678453a8Sspeer 734678453a8Sspeer status = nxge_get_config_properties(nxgep); 735678453a8Sspeer 736678453a8Sspeer if (status != NXGE_OK) { 737678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7384045d941Ssowmini "get_hw create failed")); 739678453a8Sspeer goto nxge_attach_fail; 740678453a8Sspeer } 74144961713Sgirish } 74244961713Sgirish 74344961713Sgirish /* 74444961713Sgirish * Setup the Kstats for the driver. 74544961713Sgirish */ 74644961713Sgirish nxge_setup_kstats(nxgep); 74744961713Sgirish 748678453a8Sspeer if (!isLDOMguest(nxgep)) 749678453a8Sspeer nxge_setup_param(nxgep); 75044961713Sgirish 75144961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 75244961713Sgirish if (status != NXGE_OK) { 75344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 75444961713Sgirish goto nxge_attach_fail; 75544961713Sgirish } 75644961713Sgirish 75744961713Sgirish nxge_hw_id_init(nxgep); 758678453a8Sspeer 759678453a8Sspeer if (!isLDOMguest(nxgep)) 760678453a8Sspeer nxge_hw_init_niu_common(nxgep); 76144961713Sgirish 76244961713Sgirish status = nxge_setup_mutexes(nxgep); 76344961713Sgirish if (status != NXGE_OK) { 76444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 76544961713Sgirish goto nxge_attach_fail; 76644961713Sgirish } 76744961713Sgirish 768678453a8Sspeer #if defined(sun4v) 769678453a8Sspeer if (isLDOMguest(nxgep)) { 770678453a8Sspeer /* Find our VR & channel sets. */ 771678453a8Sspeer status = nxge_hio_vr_add(nxgep); 772678453a8Sspeer goto nxge_attach_exit; 773678453a8Sspeer } 774678453a8Sspeer #endif 775678453a8Sspeer 77644961713Sgirish status = nxge_setup_dev(nxgep); 77744961713Sgirish if (status != DDI_SUCCESS) { 77844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 77944961713Sgirish goto nxge_attach_fail; 78044961713Sgirish } 78144961713Sgirish 78244961713Sgirish status = nxge_add_intrs(nxgep); 78344961713Sgirish if (status != DDI_SUCCESS) { 78444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 78544961713Sgirish goto nxge_attach_fail; 78644961713Sgirish } 78744961713Sgirish status = nxge_add_soft_intrs(nxgep); 78844961713Sgirish if (status != DDI_SUCCESS) { 789678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 790678453a8Sspeer "add_soft_intr failed")); 79144961713Sgirish goto nxge_attach_fail; 79244961713Sgirish } 79344961713Sgirish 79444961713Sgirish /* 79544961713Sgirish * Enable interrupts. 79644961713Sgirish */ 79744961713Sgirish nxge_intrs_enable(nxgep); 79844961713Sgirish 799678453a8Sspeer // If a guest, register with vio_net instead. 8002e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 80144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 802678453a8Sspeer "unable to register to mac layer (%d)", status)); 80344961713Sgirish goto nxge_attach_fail; 80444961713Sgirish } 80544961713Sgirish 80644961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 80744961713Sgirish 808678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 809678453a8Sspeer "registered to mac (instance %d)", instance)); 81044961713Sgirish 81144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 81244961713Sgirish 81344961713Sgirish goto nxge_attach_exit; 81444961713Sgirish 81544961713Sgirish nxge_attach_fail: 81644961713Sgirish nxge_unattach(nxgep); 8172e59129aSraghus goto nxge_attach_fail1; 8182e59129aSraghus 8192e59129aSraghus nxge_attach_fail5: 8202e59129aSraghus /* 8212e59129aSraghus * Tear down the ndd parameters setup. 8222e59129aSraghus */ 8232e59129aSraghus nxge_destroy_param(nxgep); 8242e59129aSraghus 8252e59129aSraghus /* 8262e59129aSraghus * Tear down the kstat setup. 8272e59129aSraghus */ 8282e59129aSraghus nxge_destroy_kstats(nxgep); 8292e59129aSraghus 8302e59129aSraghus nxge_attach_fail4: 8312e59129aSraghus if (nxgep->nxge_hw_p) { 8322e59129aSraghus nxge_uninit_common_dev(nxgep); 8332e59129aSraghus nxgep->nxge_hw_p = NULL; 8342e59129aSraghus } 8352e59129aSraghus 8362e59129aSraghus nxge_attach_fail3: 8372e59129aSraghus /* 8382e59129aSraghus * Unmap the register setup. 8392e59129aSraghus */ 8402e59129aSraghus nxge_unmap_regs(nxgep); 8412e59129aSraghus 8422e59129aSraghus nxge_fm_fini(nxgep); 8432e59129aSraghus 8442e59129aSraghus nxge_attach_fail2: 8452e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 8462e59129aSraghus 8472e59129aSraghus nxge_attach_fail1: 84856d930aeSspeer if (status != NXGE_OK) 84956d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 85044961713Sgirish nxgep = NULL; 85144961713Sgirish 85244961713Sgirish nxge_attach_exit: 85344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 8544045d941Ssowmini status)); 85544961713Sgirish 85644961713Sgirish return (status); 85744961713Sgirish } 85844961713Sgirish 85944961713Sgirish static int 86044961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 86144961713Sgirish { 86244961713Sgirish int status = DDI_SUCCESS; 86344961713Sgirish int instance; 86444961713Sgirish p_nxge_t nxgep = NULL; 86544961713Sgirish 86644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 86744961713Sgirish instance = ddi_get_instance(dip); 86844961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 86944961713Sgirish if (nxgep == NULL) { 87044961713Sgirish status = DDI_FAILURE; 87144961713Sgirish goto nxge_detach_exit; 87244961713Sgirish } 87344961713Sgirish 87444961713Sgirish switch (cmd) { 87544961713Sgirish case DDI_DETACH: 87644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 87744961713Sgirish break; 87844961713Sgirish 87944961713Sgirish case DDI_PM_SUSPEND: 88044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 88144961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 88244961713Sgirish nxge_suspend(nxgep); 88344961713Sgirish break; 88444961713Sgirish 88544961713Sgirish case DDI_SUSPEND: 88644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 88744961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 88844961713Sgirish nxgep->suspended = DDI_SUSPEND; 88944961713Sgirish nxge_suspend(nxgep); 89044961713Sgirish } 89144961713Sgirish break; 89244961713Sgirish 89344961713Sgirish default: 89444961713Sgirish status = DDI_FAILURE; 89544961713Sgirish } 89644961713Sgirish 89744961713Sgirish if (cmd != DDI_DETACH) 89844961713Sgirish goto nxge_detach_exit; 89944961713Sgirish 90044961713Sgirish /* 90144961713Sgirish * Stop the xcvr polling. 90244961713Sgirish */ 90344961713Sgirish nxgep->suspended = cmd; 90444961713Sgirish 90544961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 90644961713Sgirish 907678453a8Sspeer if (isLDOMguest(nxgep)) { 908678453a8Sspeer nxge_hio_unregister(nxgep); 909678453a8Sspeer } else if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 91044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9114045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 91244961713Sgirish return (DDI_FAILURE); 91344961713Sgirish } 91444961713Sgirish 91544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9164045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 91744961713Sgirish 91844961713Sgirish nxge_unattach(nxgep); 91944961713Sgirish nxgep = NULL; 92044961713Sgirish 92144961713Sgirish nxge_detach_exit: 92244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9234045d941Ssowmini status)); 92444961713Sgirish 92544961713Sgirish return (status); 92644961713Sgirish } 92744961713Sgirish 92844961713Sgirish static void 92944961713Sgirish nxge_unattach(p_nxge_t nxgep) 93044961713Sgirish { 93144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 93244961713Sgirish 93344961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 93444961713Sgirish return; 93544961713Sgirish } 93644961713Sgirish 93798ecde52Stm nxgep->nxge_magic = 0; 93898ecde52Stm 93944961713Sgirish if (nxgep->nxge_timerid) { 94044961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 94144961713Sgirish nxgep->nxge_timerid = 0; 94244961713Sgirish } 94344961713Sgirish 944*6f157acbSml /* 945*6f157acbSml * If this flag is set, it will affect the Neptune 946*6f157acbSml * only. 947*6f157acbSml */ 948*6f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 949*6f157acbSml nxge_niu_peu_reset(nxgep); 950*6f157acbSml } 951*6f157acbSml 952678453a8Sspeer #if defined(sun4v) 953678453a8Sspeer if (isLDOMguest(nxgep)) { 954d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 955678453a8Sspeer } 956678453a8Sspeer #endif 957678453a8Sspeer 95853560810Ssbehera if (nxgep->nxge_hw_p) { 95953560810Ssbehera nxge_uninit_common_dev(nxgep); 96053560810Ssbehera nxgep->nxge_hw_p = NULL; 96153560810Ssbehera } 96253560810Ssbehera 96344961713Sgirish #if defined(sun4v) 96444961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 96544961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 96644961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 96744961713Sgirish } 96844961713Sgirish #endif 96944961713Sgirish /* 97044961713Sgirish * Stop any further interrupts. 97144961713Sgirish */ 97244961713Sgirish nxge_remove_intrs(nxgep); 97344961713Sgirish 97444961713Sgirish /* remove soft interrups */ 97544961713Sgirish nxge_remove_soft_intrs(nxgep); 97644961713Sgirish 97744961713Sgirish /* 97844961713Sgirish * Stop the device and free resources. 97944961713Sgirish */ 980678453a8Sspeer if (!isLDOMguest(nxgep)) { 981678453a8Sspeer nxge_destroy_dev(nxgep); 982678453a8Sspeer } 98344961713Sgirish 98444961713Sgirish /* 98544961713Sgirish * Tear down the ndd parameters setup. 98644961713Sgirish */ 98744961713Sgirish nxge_destroy_param(nxgep); 98844961713Sgirish 98944961713Sgirish /* 99044961713Sgirish * Tear down the kstat setup. 99144961713Sgirish */ 99244961713Sgirish nxge_destroy_kstats(nxgep); 99344961713Sgirish 99444961713Sgirish /* 99544961713Sgirish * Destroy all mutexes. 99644961713Sgirish */ 99744961713Sgirish nxge_destroy_mutexes(nxgep); 99844961713Sgirish 99944961713Sgirish /* 100044961713Sgirish * Remove the list of ndd parameters which 100144961713Sgirish * were setup during attach. 100244961713Sgirish */ 100344961713Sgirish if (nxgep->dip) { 100444961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10054045d941Ssowmini " nxge_unattach: remove all properties")); 100644961713Sgirish 100744961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 100844961713Sgirish } 100944961713Sgirish 101044961713Sgirish #if NXGE_PROPERTY 101144961713Sgirish nxge_remove_hard_properties(nxgep); 101244961713Sgirish #endif 101344961713Sgirish 101444961713Sgirish /* 101544961713Sgirish * Unmap the register setup. 101644961713Sgirish */ 101744961713Sgirish nxge_unmap_regs(nxgep); 101844961713Sgirish 101944961713Sgirish nxge_fm_fini(nxgep); 102044961713Sgirish 102144961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 102244961713Sgirish 102344961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 102444961713Sgirish } 102544961713Sgirish 1026678453a8Sspeer #if defined(sun4v) 1027678453a8Sspeer int 1028678453a8Sspeer nxge_hsvc_register( 1029678453a8Sspeer nxge_t *nxgep) 1030678453a8Sspeer { 1031678453a8Sspeer nxge_status_t status; 1032678453a8Sspeer 1033678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 1034678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 1035678453a8Sspeer bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 1036678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 1037678453a8Sspeer &nxgep->niu_min_ver)) != 0) { 1038678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1039678453a8Sspeer "nxge_attach: %s: cannot negotiate " 1040678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1041678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1042678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1043678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1044678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1045678453a8Sspeer return (DDI_FAILURE); 1046678453a8Sspeer } 1047678453a8Sspeer nxgep->niu_hsvc_available = B_TRUE; 1048678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10494045d941Ssowmini "NIU Hypervisor service enabled")); 1050678453a8Sspeer } 1051678453a8Sspeer 1052678453a8Sspeer return (DDI_SUCCESS); 1053678453a8Sspeer } 1054678453a8Sspeer #endif 1055678453a8Sspeer 105644961713Sgirish static char n2_siu_name[] = "niu"; 105744961713Sgirish 105844961713Sgirish static nxge_status_t 105944961713Sgirish nxge_map_regs(p_nxge_t nxgep) 106044961713Sgirish { 106144961713Sgirish int ddi_status = DDI_SUCCESS; 106244961713Sgirish p_dev_regs_t dev_regs; 106344961713Sgirish char buf[MAXPATHLEN + 1]; 106444961713Sgirish char *devname; 106544961713Sgirish #ifdef NXGE_DEBUG 106644961713Sgirish char *sysname; 106744961713Sgirish #endif 106844961713Sgirish off_t regsize; 106944961713Sgirish nxge_status_t status = NXGE_OK; 107014ea4bb7Ssd #if !defined(_BIG_ENDIAN) 107114ea4bb7Ssd off_t pci_offset; 107214ea4bb7Ssd uint16_t pcie_devctl; 107314ea4bb7Ssd #endif 107444961713Sgirish 1075678453a8Sspeer if (isLDOMguest(nxgep)) { 1076678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1077678453a8Sspeer } 1078678453a8Sspeer 107944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 108044961713Sgirish nxgep->dev_regs = NULL; 108144961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 108244961713Sgirish dev_regs->nxge_regh = NULL; 108344961713Sgirish dev_regs->nxge_pciregh = NULL; 108444961713Sgirish dev_regs->nxge_msix_regh = NULL; 108544961713Sgirish dev_regs->nxge_vir_regh = NULL; 108644961713Sgirish dev_regs->nxge_vir2_regh = NULL; 108759ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 108844961713Sgirish 108944961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 109044961713Sgirish ASSERT(strlen(devname) > 0); 109144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10924045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 109344961713Sgirish 109444961713Sgirish if (strstr(devname, n2_siu_name)) { 109544961713Sgirish /* N2/NIU */ 109644961713Sgirish nxgep->niu_type = N2_NIU; 109744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10984045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 109944961713Sgirish /* get function number */ 110044961713Sgirish nxgep->function_num = 11014045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 110244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11034045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 11044045d941Ssowmini nxgep->function_num)); 110544961713Sgirish } else { 110644961713Sgirish int *prop_val; 110744961713Sgirish uint_t prop_len; 110844961713Sgirish uint8_t func_num; 110944961713Sgirish 111044961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 11114045d941Ssowmini 0, "reg", 11124045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 111344961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 11144045d941Ssowmini "Reg property not found")); 111544961713Sgirish ddi_status = DDI_FAILURE; 111644961713Sgirish goto nxge_map_regs_fail0; 111744961713Sgirish 111844961713Sgirish } else { 111944961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 112044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11214045d941Ssowmini "Reg property found: fun # %d", 11224045d941Ssowmini func_num)); 112344961713Sgirish nxgep->function_num = func_num; 1124678453a8Sspeer if (isLDOMguest(nxgep)) { 1125678453a8Sspeer nxgep->function_num /= 2; 1126678453a8Sspeer return (NXGE_OK); 1127678453a8Sspeer } 112844961713Sgirish ddi_prop_free(prop_val); 112944961713Sgirish } 113044961713Sgirish } 113144961713Sgirish 113244961713Sgirish switch (nxgep->niu_type) { 113344961713Sgirish default: 113444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 113544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11364045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 113744961713Sgirish 113844961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 11394045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 11404045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 114144961713Sgirish if (ddi_status != DDI_SUCCESS) { 114244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11434045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 114444961713Sgirish goto nxge_map_regs_fail0; 114544961713Sgirish } 114644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11474045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 11484045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 11494045d941Ssowmini dev_regs->nxge_pciregh)); 115044961713Sgirish /* 115144961713Sgirish * IMP IMP 115244961713Sgirish * workaround for bit swapping bug in HW 115344961713Sgirish * which ends up in no-snoop = yes 115444961713Sgirish * resulting, in DMA not synched properly 115544961713Sgirish */ 115644961713Sgirish #if !defined(_BIG_ENDIAN) 115714ea4bb7Ssd /* workarounds for x86 systems */ 115814ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 115914ea4bb7Ssd pcie_devctl = 0x0; 116014ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 116114ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 116214ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 11634045d941Ssowmini pcie_devctl); 116444961713Sgirish #endif 116514ea4bb7Ssd 116644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 116744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11684045d941Ssowmini "nxge_map_regs: pio size 0x%x", regsize)); 116944961713Sgirish /* set up the device mapped register */ 117044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 11714045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 11724045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 117344961713Sgirish if (ddi_status != DDI_SUCCESS) { 117444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11754045d941Ssowmini "ddi_map_regs for Neptune global reg failed")); 117644961713Sgirish goto nxge_map_regs_fail1; 117744961713Sgirish } 117844961713Sgirish 117944961713Sgirish /* set up the msi/msi-x mapped register */ 118044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 118144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11824045d941Ssowmini "nxge_map_regs: msix size 0x%x", regsize)); 118344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 11844045d941Ssowmini (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 11854045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 118644961713Sgirish if (ddi_status != DDI_SUCCESS) { 118744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11884045d941Ssowmini "ddi_map_regs for msi reg failed")); 118944961713Sgirish goto nxge_map_regs_fail2; 119044961713Sgirish } 119144961713Sgirish 119244961713Sgirish /* set up the vio region mapped register */ 119344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 119444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11954045d941Ssowmini "nxge_map_regs: vio size 0x%x", regsize)); 119644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 11974045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 11984045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 119944961713Sgirish 120044961713Sgirish if (ddi_status != DDI_SUCCESS) { 120144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12024045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 120344961713Sgirish goto nxge_map_regs_fail3; 120444961713Sgirish } 120544961713Sgirish nxgep->dev_regs = dev_regs; 120644961713Sgirish 120744961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 120844961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 12094045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_pciregp); 121044961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 121144961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 12124045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 121344961713Sgirish 121444961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 121544961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 121644961713Sgirish 121744961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 121844961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 12194045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 122044961713Sgirish 122144961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 122244961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 12234045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 122444961713Sgirish 122544961713Sgirish break; 122644961713Sgirish 122744961713Sgirish case N2_NIU: 122844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 122944961713Sgirish /* 123044961713Sgirish * Set up the device mapped register (FWARC 2006/556) 123144961713Sgirish * (changed back to 1: reg starts at 1!) 123244961713Sgirish */ 123344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 123444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12354045d941Ssowmini "nxge_map_regs: dev size 0x%x", regsize)); 123644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12374045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12384045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 123944961713Sgirish 124044961713Sgirish if (ddi_status != DDI_SUCCESS) { 124144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12424045d941Ssowmini "ddi_map_regs for N2/NIU, global reg failed ")); 124344961713Sgirish goto nxge_map_regs_fail1; 124444961713Sgirish } 124544961713Sgirish 1246678453a8Sspeer /* set up the first vio region mapped register */ 124744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 124844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12494045d941Ssowmini "nxge_map_regs: vio (1) size 0x%x", regsize)); 125044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 12514045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 12524045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 125344961713Sgirish 125444961713Sgirish if (ddi_status != DDI_SUCCESS) { 125544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12564045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 125744961713Sgirish goto nxge_map_regs_fail2; 125844961713Sgirish } 1259678453a8Sspeer /* set up the second vio region mapped register */ 126044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 126144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12624045d941Ssowmini "nxge_map_regs: vio (3) size 0x%x", regsize)); 126344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 12644045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 12654045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 126644961713Sgirish 126744961713Sgirish if (ddi_status != DDI_SUCCESS) { 126844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12694045d941Ssowmini "ddi_map_regs for nxge vio2 reg failed")); 127044961713Sgirish goto nxge_map_regs_fail3; 127144961713Sgirish } 127244961713Sgirish nxgep->dev_regs = dev_regs; 127344961713Sgirish 127444961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 127544961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 127644961713Sgirish 127744961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 127844961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 12794045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 128044961713Sgirish 128144961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 128244961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 12834045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 128444961713Sgirish 128544961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 128644961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 12874045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 128844961713Sgirish 128944961713Sgirish break; 129044961713Sgirish } 129144961713Sgirish 129244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 12934045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 129444961713Sgirish 129544961713Sgirish goto nxge_map_regs_exit; 129644961713Sgirish nxge_map_regs_fail3: 129744961713Sgirish if (dev_regs->nxge_msix_regh) { 129844961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 129944961713Sgirish } 130044961713Sgirish if (dev_regs->nxge_vir_regh) { 130144961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 130244961713Sgirish } 130344961713Sgirish nxge_map_regs_fail2: 130444961713Sgirish if (dev_regs->nxge_regh) { 130544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 130644961713Sgirish } 130744961713Sgirish nxge_map_regs_fail1: 130844961713Sgirish if (dev_regs->nxge_pciregh) { 130944961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 131044961713Sgirish } 131144961713Sgirish nxge_map_regs_fail0: 131244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 131344961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 131444961713Sgirish 131544961713Sgirish nxge_map_regs_exit: 131644961713Sgirish if (ddi_status != DDI_SUCCESS) 131744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 131844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 131944961713Sgirish return (status); 132044961713Sgirish } 132144961713Sgirish 132244961713Sgirish static void 132344961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 132444961713Sgirish { 132544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1326678453a8Sspeer 1327678453a8Sspeer if (isLDOMguest(nxgep)) { 1328678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1329678453a8Sspeer return; 1330678453a8Sspeer } 1331678453a8Sspeer 133244961713Sgirish if (nxgep->dev_regs) { 133344961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 133444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13354045d941Ssowmini "==> nxge_unmap_regs: bus")); 133644961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 133744961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 133844961713Sgirish } 133944961713Sgirish if (nxgep->dev_regs->nxge_regh) { 134044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13414045d941Ssowmini "==> nxge_unmap_regs: device registers")); 134244961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 134344961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 134444961713Sgirish } 134544961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 134644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13474045d941Ssowmini "==> nxge_unmap_regs: device interrupts")); 134844961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 134944961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 135044961713Sgirish } 135144961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 135244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13534045d941Ssowmini "==> nxge_unmap_regs: vio region")); 135444961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 135544961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 135644961713Sgirish } 135744961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 135844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13594045d941Ssowmini "==> nxge_unmap_regs: vio2 region")); 136044961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 136144961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 136244961713Sgirish } 136344961713Sgirish 136444961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 136544961713Sgirish nxgep->dev_regs = NULL; 136644961713Sgirish } 136744961713Sgirish 136844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 136944961713Sgirish } 137044961713Sgirish 137144961713Sgirish static nxge_status_t 137244961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 137344961713Sgirish { 137444961713Sgirish int ddi_status = DDI_SUCCESS; 137544961713Sgirish nxge_status_t status = NXGE_OK; 137644961713Sgirish nxge_classify_t *classify_ptr; 137744961713Sgirish int partition; 137844961713Sgirish 137944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 138044961713Sgirish 138144961713Sgirish /* 138244961713Sgirish * Get the interrupt cookie so the mutexes can be 138358324dfcSspeer * Initialized. 138444961713Sgirish */ 1385678453a8Sspeer if (isLDOMguest(nxgep)) { 1386678453a8Sspeer nxgep->interrupt_cookie = 0; 1387678453a8Sspeer } else { 1388678453a8Sspeer ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 1389678453a8Sspeer &nxgep->interrupt_cookie); 1390678453a8Sspeer 1391678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 1392678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1393678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1394678453a8Sspeer ddi_status)); 1395678453a8Sspeer goto nxge_setup_mutexes_exit; 1396678453a8Sspeer } 139744961713Sgirish } 139844961713Sgirish 139998ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 140098ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 140198ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 140298ecde52Stm 140344961713Sgirish /* 140498ecde52Stm * Initialize mutexes for this device. 140544961713Sgirish */ 140644961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 14074045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 140844961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 14094045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 141044961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 14114045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1412678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1413678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 141444961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 14154045d941Ssowmini RW_DRIVER, (void *)nxgep->interrupt_cookie); 141644961713Sgirish 141744961713Sgirish classify_ptr = &nxgep->classifier; 141844961713Sgirish /* 141944961713Sgirish * FFLP Mutexes are never used in interrupt context 142044961713Sgirish * as fflp operation can take very long time to 142144961713Sgirish * complete and hence not suitable to invoke from interrupt 142244961713Sgirish * handlers. 142344961713Sgirish */ 142444961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 142559ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 14262e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 142744961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 142859ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 142944961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 143044961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 143144961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 143244961713Sgirish } 143344961713Sgirish } 143444961713Sgirish 143544961713Sgirish nxge_setup_mutexes_exit: 143644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 143759ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 143844961713Sgirish 143944961713Sgirish if (ddi_status != DDI_SUCCESS) 144044961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 144144961713Sgirish 144244961713Sgirish return (status); 144344961713Sgirish } 144444961713Sgirish 144544961713Sgirish static void 144644961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 144744961713Sgirish { 144844961713Sgirish int partition; 144944961713Sgirish nxge_classify_t *classify_ptr; 145044961713Sgirish 145144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 145244961713Sgirish RW_DESTROY(&nxgep->filter_lock); 1453678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 145444961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 145544961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 145644961713Sgirish MUTEX_DESTROY(nxgep->genlock); 145744961713Sgirish 145844961713Sgirish classify_ptr = &nxgep->classifier; 145944961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 146044961713Sgirish 146198ecde52Stm /* Destroy all polling resources. */ 146298ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 146398ecde52Stm cv_destroy(&nxgep->poll_cv); 146498ecde52Stm 146598ecde52Stm /* free data structures, based on HW type */ 14662e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 146744961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 146844961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 146944961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 147044961713Sgirish } 147144961713Sgirish } 147244961713Sgirish 147344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 147444961713Sgirish } 147544961713Sgirish 147644961713Sgirish nxge_status_t 147744961713Sgirish nxge_init(p_nxge_t nxgep) 147844961713Sgirish { 1479678453a8Sspeer nxge_status_t status = NXGE_OK; 148044961713Sgirish 148144961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 148244961713Sgirish 148314ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 148414ea4bb7Ssd return (status); 148514ea4bb7Ssd } 148614ea4bb7Ssd 148744961713Sgirish /* 148844961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 148944961713Sgirish * and receive/transmit descriptor rings. 149044961713Sgirish */ 149144961713Sgirish status = nxge_alloc_mem_pool(nxgep); 149244961713Sgirish if (status != NXGE_OK) { 149344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 149444961713Sgirish goto nxge_init_fail1; 149544961713Sgirish } 149644961713Sgirish 1497678453a8Sspeer if (!isLDOMguest(nxgep)) { 1498678453a8Sspeer /* 1499678453a8Sspeer * Initialize and enable the TXC registers. 1500678453a8Sspeer * (Globally enable the Tx controller, 1501678453a8Sspeer * enable the port, configure the dma channel bitmap, 1502678453a8Sspeer * configure the max burst size). 1503678453a8Sspeer */ 1504678453a8Sspeer status = nxge_txc_init(nxgep); 1505678453a8Sspeer if (status != NXGE_OK) { 1506678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1507678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 1508678453a8Sspeer goto nxge_init_fail2; 1509678453a8Sspeer } 151044961713Sgirish } 151144961713Sgirish 151244961713Sgirish /* 151344961713Sgirish * Initialize and enable TXDMA channels. 151444961713Sgirish */ 151544961713Sgirish status = nxge_init_txdma_channels(nxgep); 151644961713Sgirish if (status != NXGE_OK) { 151744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 151844961713Sgirish goto nxge_init_fail3; 151944961713Sgirish } 152044961713Sgirish 152144961713Sgirish /* 152244961713Sgirish * Initialize and enable RXDMA channels. 152344961713Sgirish */ 152444961713Sgirish status = nxge_init_rxdma_channels(nxgep); 152544961713Sgirish if (status != NXGE_OK) { 152644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 152744961713Sgirish goto nxge_init_fail4; 152844961713Sgirish } 152944961713Sgirish 1530678453a8Sspeer /* 1531678453a8Sspeer * The guest domain is now done. 1532678453a8Sspeer */ 1533678453a8Sspeer if (isLDOMguest(nxgep)) { 1534678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1535678453a8Sspeer goto nxge_init_exit; 1536678453a8Sspeer } 1537678453a8Sspeer 153844961713Sgirish /* 153944961713Sgirish * Initialize TCAM and FCRAM (Neptune). 154044961713Sgirish */ 154144961713Sgirish status = nxge_classify_init(nxgep); 154244961713Sgirish if (status != NXGE_OK) { 154344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 154444961713Sgirish goto nxge_init_fail5; 154544961713Sgirish } 154644961713Sgirish 154744961713Sgirish /* 154844961713Sgirish * Initialize ZCP 154944961713Sgirish */ 155044961713Sgirish status = nxge_zcp_init(nxgep); 155144961713Sgirish if (status != NXGE_OK) { 155244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 155344961713Sgirish goto nxge_init_fail5; 155444961713Sgirish } 155544961713Sgirish 155644961713Sgirish /* 155744961713Sgirish * Initialize IPP. 155844961713Sgirish */ 155944961713Sgirish status = nxge_ipp_init(nxgep); 156044961713Sgirish if (status != NXGE_OK) { 156144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 156244961713Sgirish goto nxge_init_fail5; 156344961713Sgirish } 156444961713Sgirish 156544961713Sgirish /* 156644961713Sgirish * Initialize the MAC block. 156744961713Sgirish */ 156844961713Sgirish status = nxge_mac_init(nxgep); 156944961713Sgirish if (status != NXGE_OK) { 157044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 157144961713Sgirish goto nxge_init_fail5; 157244961713Sgirish } 157344961713Sgirish 1574678453a8Sspeer nxge_intrs_enable(nxgep); /* XXX What changes do I need to make here? */ 157544961713Sgirish 157644961713Sgirish /* 157744961713Sgirish * Enable hardware interrupts. 157844961713Sgirish */ 157944961713Sgirish nxge_intr_hw_enable(nxgep); 158044961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 158144961713Sgirish 158244961713Sgirish goto nxge_init_exit; 158344961713Sgirish 158444961713Sgirish nxge_init_fail5: 158544961713Sgirish nxge_uninit_rxdma_channels(nxgep); 158644961713Sgirish nxge_init_fail4: 158744961713Sgirish nxge_uninit_txdma_channels(nxgep); 158844961713Sgirish nxge_init_fail3: 1589678453a8Sspeer if (!isLDOMguest(nxgep)) { 1590678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1591678453a8Sspeer } 159244961713Sgirish nxge_init_fail2: 159344961713Sgirish nxge_free_mem_pool(nxgep); 159444961713Sgirish nxge_init_fail1: 159544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15964045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 159744961713Sgirish return (status); 159844961713Sgirish 159944961713Sgirish nxge_init_exit: 160044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 16014045d941Ssowmini status)); 160244961713Sgirish return (status); 160344961713Sgirish } 160444961713Sgirish 160544961713Sgirish 160644961713Sgirish timeout_id_t 160744961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 160844961713Sgirish { 16094045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 161044961713Sgirish return (timeout(func, (caddr_t)nxgep, 16114045d941Ssowmini drv_usectohz(1000 * msec))); 161244961713Sgirish } 161344961713Sgirish return (NULL); 161444961713Sgirish } 161544961713Sgirish 161644961713Sgirish /*ARGSUSED*/ 161744961713Sgirish void 161844961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 161944961713Sgirish { 162044961713Sgirish if (timerid) { 162144961713Sgirish (void) untimeout(timerid); 162244961713Sgirish } 162344961713Sgirish } 162444961713Sgirish 162544961713Sgirish void 162644961713Sgirish nxge_uninit(p_nxge_t nxgep) 162744961713Sgirish { 162844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 162944961713Sgirish 163044961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 163144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16324045d941Ssowmini "==> nxge_uninit: not initialized")); 163344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16344045d941Ssowmini "<== nxge_uninit")); 163544961713Sgirish return; 163644961713Sgirish } 163744961713Sgirish 163844961713Sgirish /* stop timer */ 163944961713Sgirish if (nxgep->nxge_timerid) { 164044961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 164144961713Sgirish nxgep->nxge_timerid = 0; 164244961713Sgirish } 164344961713Sgirish 164444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 164544961713Sgirish (void) nxge_intr_hw_disable(nxgep); 164644961713Sgirish 164744961713Sgirish /* 164844961713Sgirish * Reset the receive MAC side. 164944961713Sgirish */ 165044961713Sgirish (void) nxge_rx_mac_disable(nxgep); 165144961713Sgirish 165244961713Sgirish /* Disable and soft reset the IPP */ 1653678453a8Sspeer if (!isLDOMguest(nxgep)) 1654678453a8Sspeer (void) nxge_ipp_disable(nxgep); 165544961713Sgirish 1656a3c5bd6dSspeer /* Free classification resources */ 1657a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1658a3c5bd6dSspeer 165944961713Sgirish /* 166044961713Sgirish * Reset the transmit/receive DMA side. 166144961713Sgirish */ 166244961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 166344961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 166444961713Sgirish 166544961713Sgirish nxge_uninit_txdma_channels(nxgep); 166644961713Sgirish nxge_uninit_rxdma_channels(nxgep); 166744961713Sgirish 166844961713Sgirish /* 166944961713Sgirish * Reset the transmit MAC side. 167044961713Sgirish */ 167144961713Sgirish (void) nxge_tx_mac_disable(nxgep); 167244961713Sgirish 167344961713Sgirish nxge_free_mem_pool(nxgep); 167444961713Sgirish 1675*6f157acbSml /* 1676*6f157acbSml * Start the timer if the reset flag is not set. 1677*6f157acbSml * If this reset flag is set, the link monitor 1678*6f157acbSml * will not be started in order to stop furthur bus 1679*6f157acbSml * activities coming from this interface. 1680*6f157acbSml * The driver will start the monitor function 1681*6f157acbSml * if the interface was initialized again later. 1682*6f157acbSml */ 1683*6f157acbSml if (!nxge_peu_reset_enable) { 1684*6f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 1685*6f157acbSml } 168644961713Sgirish 168744961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 168844961713Sgirish 168944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 16904045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 169144961713Sgirish } 169244961713Sgirish 169344961713Sgirish void 169444961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 169544961713Sgirish { 1696adfcba55Sjoycey #if defined(__i386) 1697adfcba55Sjoycey size_t reg; 1698adfcba55Sjoycey #else 169944961713Sgirish uint64_t reg; 1700adfcba55Sjoycey #endif 170144961713Sgirish uint64_t regdata; 170244961713Sgirish int i, retry; 170344961713Sgirish 170444961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 170544961713Sgirish regdata = 0; 170644961713Sgirish retry = 1; 170744961713Sgirish 170844961713Sgirish for (i = 0; i < retry; i++) { 170944961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 171044961713Sgirish } 171144961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 171244961713Sgirish } 171344961713Sgirish 171444961713Sgirish void 171544961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 171644961713Sgirish { 1717adfcba55Sjoycey #if defined(__i386) 1718adfcba55Sjoycey size_t reg; 1719adfcba55Sjoycey #else 172044961713Sgirish uint64_t reg; 1721adfcba55Sjoycey #endif 172244961713Sgirish uint64_t buf[2]; 172344961713Sgirish 172444961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 17257a8b1321Sjoycey #if defined(__i386) 17267a8b1321Sjoycey reg = (size_t)buf[0]; 17277a8b1321Sjoycey #else 172844961713Sgirish reg = buf[0]; 17297a8b1321Sjoycey #endif 173044961713Sgirish 173144961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 173244961713Sgirish } 173344961713Sgirish 173444961713Sgirish 173544961713Sgirish nxge_os_mutex_t nxgedebuglock; 173644961713Sgirish int nxge_debug_init = 0; 173744961713Sgirish 173844961713Sgirish /*ARGSUSED*/ 173944961713Sgirish /*VARARGS*/ 174044961713Sgirish void 174144961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 174244961713Sgirish { 174344961713Sgirish char msg_buffer[1048]; 174444961713Sgirish char prefix_buffer[32]; 174544961713Sgirish int instance; 174644961713Sgirish uint64_t debug_level; 174744961713Sgirish int cmn_level = CE_CONT; 174844961713Sgirish va_list ap; 174944961713Sgirish 1750678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1751678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1752678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1753678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1754678453a8Sspeer } 1755678453a8Sspeer 175644961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 17574045d941Ssowmini nxgep->nxge_debug_level; 175844961713Sgirish 175944961713Sgirish if ((level & debug_level) || 17604045d941Ssowmini (level == NXGE_NOTE) || 17614045d941Ssowmini (level == NXGE_ERR_CTL)) { 176244961713Sgirish /* do the msg processing */ 176344961713Sgirish if (nxge_debug_init == 0) { 176444961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 176544961713Sgirish nxge_debug_init = 1; 176644961713Sgirish } 176744961713Sgirish 176844961713Sgirish MUTEX_ENTER(&nxgedebuglock); 176944961713Sgirish 177044961713Sgirish if ((level & NXGE_NOTE)) { 177144961713Sgirish cmn_level = CE_NOTE; 177244961713Sgirish } 177344961713Sgirish 177444961713Sgirish if (level & NXGE_ERR_CTL) { 177544961713Sgirish cmn_level = CE_WARN; 177644961713Sgirish } 177744961713Sgirish 177844961713Sgirish va_start(ap, fmt); 177944961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 178044961713Sgirish va_end(ap); 178144961713Sgirish if (nxgep == NULL) { 178244961713Sgirish instance = -1; 178344961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 178444961713Sgirish } else { 178544961713Sgirish instance = nxgep->instance; 178644961713Sgirish (void) sprintf(prefix_buffer, 17874045d941Ssowmini "%s%d :", "nxge", instance); 178844961713Sgirish } 178944961713Sgirish 179044961713Sgirish MUTEX_EXIT(&nxgedebuglock); 179144961713Sgirish cmn_err(cmn_level, "!%s %s\n", 17924045d941Ssowmini prefix_buffer, msg_buffer); 179344961713Sgirish 179444961713Sgirish } 179544961713Sgirish } 179644961713Sgirish 179744961713Sgirish char * 179844961713Sgirish nxge_dump_packet(char *addr, int size) 179944961713Sgirish { 180044961713Sgirish uchar_t *ap = (uchar_t *)addr; 180144961713Sgirish int i; 180244961713Sgirish static char etherbuf[1024]; 180344961713Sgirish char *cp = etherbuf; 180444961713Sgirish char digits[] = "0123456789abcdef"; 180544961713Sgirish 180644961713Sgirish if (!size) 180744961713Sgirish size = 60; 180844961713Sgirish 180944961713Sgirish if (size > MAX_DUMP_SZ) { 181044961713Sgirish /* Dump the leading bytes */ 181144961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 181244961713Sgirish if (*ap > 0x0f) 181344961713Sgirish *cp++ = digits[*ap >> 4]; 181444961713Sgirish *cp++ = digits[*ap++ & 0xf]; 181544961713Sgirish *cp++ = ':'; 181644961713Sgirish } 181744961713Sgirish for (i = 0; i < 20; i++) 181844961713Sgirish *cp++ = '.'; 181944961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 182044961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 182144961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 182244961713Sgirish if (*ap > 0x0f) 182344961713Sgirish *cp++ = digits[*ap >> 4]; 182444961713Sgirish *cp++ = digits[*ap++ & 0xf]; 182544961713Sgirish *cp++ = ':'; 182644961713Sgirish } 182744961713Sgirish } else { 182844961713Sgirish for (i = 0; i < size; i++) { 182944961713Sgirish if (*ap > 0x0f) 183044961713Sgirish *cp++ = digits[*ap >> 4]; 183144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 183244961713Sgirish *cp++ = ':'; 183344961713Sgirish } 183444961713Sgirish } 183544961713Sgirish *--cp = 0; 183644961713Sgirish return (etherbuf); 183744961713Sgirish } 183844961713Sgirish 183944961713Sgirish #ifdef NXGE_DEBUG 184044961713Sgirish static void 184144961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 184244961713Sgirish { 184344961713Sgirish ddi_acc_handle_t cfg_handle; 184444961713Sgirish p_pci_cfg_t cfg_ptr; 184544961713Sgirish ddi_acc_handle_t dev_handle; 184644961713Sgirish char *dev_ptr; 184744961713Sgirish ddi_acc_handle_t pci_config_handle; 184844961713Sgirish uint32_t regval; 184944961713Sgirish int i; 185044961713Sgirish 185144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 185244961713Sgirish 185344961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 185444961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 185544961713Sgirish 18562e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 185744961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 185844961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 185944961713Sgirish 186044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 186159ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 186244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 186359ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 186459ac0c16Sdavemq &cfg_ptr->vendorid)); 186544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 186659ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 186759ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 186859ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 186944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 187059ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 187159ac0c16Sdavemq "bar1c 0x%x", 187259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 187359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 187459ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 187559ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 187644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 187759ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 187859ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 187959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 188059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 188159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 188259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 188344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 188459ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 188559ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 188644961713Sgirish 188744961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 188844961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 188944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 189059ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 189159ac0c16Sdavemq "last 0x%llx ", 189259ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 189359ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 189459ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 189559ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 189659ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 189759ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 189859ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 189959ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 190044961713Sgirish } 190144961713Sgirish } 190244961713Sgirish 190344961713Sgirish #endif 190444961713Sgirish 190544961713Sgirish static void 190644961713Sgirish nxge_suspend(p_nxge_t nxgep) 190744961713Sgirish { 190844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 190944961713Sgirish 191044961713Sgirish nxge_intrs_disable(nxgep); 191144961713Sgirish nxge_destroy_dev(nxgep); 191244961713Sgirish 191344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 191444961713Sgirish } 191544961713Sgirish 191644961713Sgirish static nxge_status_t 191744961713Sgirish nxge_resume(p_nxge_t nxgep) 191844961713Sgirish { 191944961713Sgirish nxge_status_t status = NXGE_OK; 192044961713Sgirish 192144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 192244961713Sgirish 192391c98b31Sjoycey nxgep->suspended = DDI_RESUME; 192491c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 192591c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 192691c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 192791c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 192891c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 192991c98b31Sjoycey nxge_intrs_enable(nxgep); 193044961713Sgirish nxgep->suspended = 0; 193144961713Sgirish 193244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19334045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 193444961713Sgirish return (status); 193544961713Sgirish } 193644961713Sgirish 193744961713Sgirish static nxge_status_t 193844961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 193944961713Sgirish { 194044961713Sgirish nxge_status_t status = NXGE_OK; 194144961713Sgirish 194244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 194359ac0c16Sdavemq nxgep->mac.portnum)); 194444961713Sgirish 194544961713Sgirish status = nxge_link_init(nxgep); 194614ea4bb7Ssd 194714ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 194814ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19494045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 195014ea4bb7Ssd status = NXGE_ERROR; 195114ea4bb7Ssd } 195214ea4bb7Ssd 195344961713Sgirish if (status != NXGE_OK) { 195444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19554045d941Ssowmini " nxge_setup_dev status " 19564045d941Ssowmini "(xcvr init 0x%08x)", status)); 195744961713Sgirish goto nxge_setup_dev_exit; 195844961713Sgirish } 195944961713Sgirish 196044961713Sgirish nxge_setup_dev_exit: 196144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19624045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 19634045d941Ssowmini nxgep->mac.portnum, status)); 196444961713Sgirish 196544961713Sgirish return (status); 196644961713Sgirish } 196744961713Sgirish 196844961713Sgirish static void 196944961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 197044961713Sgirish { 197144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 197244961713Sgirish 197344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 197444961713Sgirish 197544961713Sgirish (void) nxge_hw_stop(nxgep); 197644961713Sgirish 197744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 197844961713Sgirish } 197944961713Sgirish 198044961713Sgirish static nxge_status_t 198144961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 198244961713Sgirish { 198344961713Sgirish int ddi_status = DDI_SUCCESS; 198444961713Sgirish uint_t count; 198544961713Sgirish ddi_dma_cookie_t cookie; 198644961713Sgirish uint_t iommu_pagesize; 198744961713Sgirish nxge_status_t status = NXGE_OK; 198844961713Sgirish 1989678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 199044961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 199144961713Sgirish if (nxgep->niu_type != N2_NIU) { 199244961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 199344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19944045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 19954045d941Ssowmini " default_block_size %d iommu_pagesize %d", 19964045d941Ssowmini nxgep->sys_page_sz, 19974045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 19984045d941Ssowmini nxgep->rx_default_block_size, 19994045d941Ssowmini iommu_pagesize)); 200044961713Sgirish 200144961713Sgirish if (iommu_pagesize != 0) { 200244961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 200344961713Sgirish if (iommu_pagesize > 0x4000) 200444961713Sgirish nxgep->sys_page_sz = 0x4000; 200544961713Sgirish } else { 200644961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 200744961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 200844961713Sgirish } 200944961713Sgirish } 201044961713Sgirish } 201144961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 201244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20134045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20144045d941Ssowmini "default_block_size %d page mask %d", 20154045d941Ssowmini nxgep->sys_page_sz, 20164045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20174045d941Ssowmini nxgep->rx_default_block_size, 20184045d941Ssowmini nxgep->sys_page_mask)); 201944961713Sgirish 202044961713Sgirish 202144961713Sgirish switch (nxgep->sys_page_sz) { 202244961713Sgirish default: 202344961713Sgirish nxgep->sys_page_sz = 0x1000; 202444961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 202544961713Sgirish nxgep->rx_default_block_size = 0x1000; 202644961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 202744961713Sgirish break; 202844961713Sgirish case 0x1000: 202944961713Sgirish nxgep->rx_default_block_size = 0x1000; 203044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 203144961713Sgirish break; 203244961713Sgirish case 0x2000: 203344961713Sgirish nxgep->rx_default_block_size = 0x2000; 203444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 203544961713Sgirish break; 203644961713Sgirish case 0x4000: 203744961713Sgirish nxgep->rx_default_block_size = 0x4000; 203844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 203944961713Sgirish break; 204044961713Sgirish case 0x8000: 204144961713Sgirish nxgep->rx_default_block_size = 0x8000; 204244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 204344961713Sgirish break; 204444961713Sgirish } 204544961713Sgirish 204644961713Sgirish #ifndef USE_RX_BIG_BUF 204744961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 204844961713Sgirish #else 204944961713Sgirish nxgep->rx_default_block_size = 0x2000; 205044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 205144961713Sgirish #endif 205244961713Sgirish /* 205344961713Sgirish * Get the system DMA burst size. 205444961713Sgirish */ 205544961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 20564045d941Ssowmini DDI_DMA_DONTWAIT, 0, 20574045d941Ssowmini &nxgep->dmasparehandle); 205844961713Sgirish if (ddi_status != DDI_SUCCESS) { 205944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20604045d941Ssowmini "ddi_dma_alloc_handle: failed " 20614045d941Ssowmini " status 0x%x", ddi_status)); 206244961713Sgirish goto nxge_get_soft_properties_exit; 206344961713Sgirish } 206444961713Sgirish 206544961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 20664045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 20674045d941Ssowmini sizeof (nxgep->dmasparehandle), 20684045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 20694045d941Ssowmini DDI_DMA_DONTWAIT, 0, 20704045d941Ssowmini &cookie, &count); 207144961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 207244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20734045d941Ssowmini "Binding spare handle to find system" 20744045d941Ssowmini " burstsize failed.")); 207544961713Sgirish ddi_status = DDI_FAILURE; 207644961713Sgirish goto nxge_get_soft_properties_fail1; 207744961713Sgirish } 207844961713Sgirish 207944961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 208044961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 208144961713Sgirish 208244961713Sgirish nxge_get_soft_properties_fail1: 208344961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 208444961713Sgirish 208544961713Sgirish nxge_get_soft_properties_exit: 208644961713Sgirish 208744961713Sgirish if (ddi_status != DDI_SUCCESS) 208844961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 208944961713Sgirish 209044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20914045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 209244961713Sgirish return (status); 209344961713Sgirish } 209444961713Sgirish 209544961713Sgirish static nxge_status_t 209644961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 209744961713Sgirish { 209844961713Sgirish nxge_status_t status = NXGE_OK; 209944961713Sgirish 210044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 210144961713Sgirish 210244961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 210344961713Sgirish if (status != NXGE_OK) { 210444961713Sgirish return (NXGE_ERROR); 210544961713Sgirish } 210644961713Sgirish 210744961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 210844961713Sgirish if (status != NXGE_OK) { 210944961713Sgirish nxge_free_rx_mem_pool(nxgep); 211044961713Sgirish return (NXGE_ERROR); 211144961713Sgirish } 211244961713Sgirish 211344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 211444961713Sgirish return (NXGE_OK); 211544961713Sgirish } 211644961713Sgirish 211744961713Sgirish static void 211844961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 211944961713Sgirish { 212044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 212144961713Sgirish 212244961713Sgirish nxge_free_rx_mem_pool(nxgep); 212344961713Sgirish nxge_free_tx_mem_pool(nxgep); 212444961713Sgirish 212544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 212644961713Sgirish } 212744961713Sgirish 2128678453a8Sspeer nxge_status_t 212944961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 213044961713Sgirish { 2131678453a8Sspeer uint32_t rdc_max; 213244961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 213344961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 213444961713Sgirish p_nxge_dma_pool_t dma_poolp; 213544961713Sgirish p_nxge_dma_common_t *dma_buf_p; 213644961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 213744961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 213844961713Sgirish uint32_t *num_chunks; /* per dma */ 213944961713Sgirish nxge_status_t status = NXGE_OK; 214044961713Sgirish 214144961713Sgirish uint32_t nxge_port_rbr_size; 214244961713Sgirish uint32_t nxge_port_rbr_spare_size; 214344961713Sgirish uint32_t nxge_port_rcr_size; 2144678453a8Sspeer uint32_t rx_cntl_alloc_size; 214544961713Sgirish 214644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 214744961713Sgirish 214844961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 214944961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2150678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 215144961713Sgirish 215244961713Sgirish /* 2153678453a8Sspeer * Allocate memory for the common DMA data structures. 215444961713Sgirish */ 215544961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 21564045d941Ssowmini KM_SLEEP); 215744961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 21584045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 215944961713Sgirish 216044961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 21614045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 216244961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 21634045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 216444961713Sgirish 216544961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 21664045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 216744961713Sgirish 216844961713Sgirish /* 2169678453a8Sspeer * Assume that each DMA channel will be configured with 2170678453a8Sspeer * the default block size. 2171678453a8Sspeer * rbr block counts are modulo the batch count (16). 217244961713Sgirish */ 217344961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 217444961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 217544961713Sgirish 217644961713Sgirish if (!nxge_port_rbr_size) { 217744961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 217844961713Sgirish } 217944961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 218044961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 21814045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 218244961713Sgirish } 218344961713Sgirish 218444961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 218544961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 218644961713Sgirish 218744961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 218844961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 21894045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 219044961713Sgirish } 219130ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 219230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 219330ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 219430ac2e7bSml "set to default %d", 219530ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 219630ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 219730ac2e7bSml } 219830ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 219930ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 220030ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 220130ac2e7bSml "set to default %d", 220230ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 220330ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 220430ac2e7bSml } 220544961713Sgirish 220644961713Sgirish /* 220744961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 220844961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 220944961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 221044961713Sgirish * function). 221144961713Sgirish */ 221244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 221344961713Sgirish if (nxgep->niu_type == N2_NIU) { 221444961713Sgirish nxge_port_rbr_spare_size = 0; 221544961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 22164045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 221744961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 221844961713Sgirish } 221944961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 22204045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 222144961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 222244961713Sgirish } 222344961713Sgirish } 222444961713Sgirish #endif 222544961713Sgirish 222644961713Sgirish /* 222744961713Sgirish * Addresses of receive block ring, receive completion ring and the 222844961713Sgirish * mailbox must be all cache-aligned (64 bytes). 222944961713Sgirish */ 223044961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 223144961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 223244961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 223344961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 223444961713Sgirish 223544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 22364045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 22374045d941Ssowmini "nxge_port_rcr_size = %d " 22384045d941Ssowmini "rx_cntl_alloc_size = %d", 22394045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 22404045d941Ssowmini nxge_port_rcr_size, 22414045d941Ssowmini rx_cntl_alloc_size)); 224244961713Sgirish 224344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 224444961713Sgirish if (nxgep->niu_type == N2_NIU) { 2245678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2246678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2247678453a8Sspeer 224844961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 224944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22504045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22514045d941Ssowmini " must be power of 2")); 225244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 225344961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 225444961713Sgirish } 225544961713Sgirish 225644961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 225744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22584045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22594045d941Ssowmini " limit size to 4M")); 226044961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 226144961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 226244961713Sgirish } 226344961713Sgirish 226444961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 226544961713Sgirish rx_cntl_alloc_size = 0x2000; 226644961713Sgirish } 226744961713Sgirish } 226844961713Sgirish #endif 226944961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 227044961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2271678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2272678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 227344961713Sgirish 2274678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 227544961713Sgirish dma_poolp->num_chunks = num_chunks; 227644961713Sgirish dma_poolp->buf_allocated = B_TRUE; 227744961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 227844961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 227944961713Sgirish 2280678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 228144961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 228244961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 228344961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 228444961713Sgirish 2285678453a8Sspeer /* Allocate the receive rings, too. */ 2286678453a8Sspeer nxgep->rx_rbr_rings = 22874045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2288678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 22894045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2290678453a8Sspeer nxgep->rx_rcr_rings = 22914045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2292678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 22934045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2294678453a8Sspeer nxgep->rx_mbox_areas_p = 22954045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2296678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 22974045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2298678453a8Sspeer 2299678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2300678453a8Sspeer p_cfgp->max_rdcs; 230144961713Sgirish 230244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 23034045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 230444961713Sgirish 2305678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2306678453a8Sspeer return (status); 2307678453a8Sspeer } 2308678453a8Sspeer 2309678453a8Sspeer /* 2310678453a8Sspeer * nxge_alloc_rxb 2311678453a8Sspeer * 2312678453a8Sspeer * Allocate buffers for an RDC. 2313678453a8Sspeer * 2314678453a8Sspeer * Arguments: 2315678453a8Sspeer * nxgep 2316678453a8Sspeer * channel The channel to map into our kernel space. 2317678453a8Sspeer * 2318678453a8Sspeer * Notes: 2319678453a8Sspeer * 2320678453a8Sspeer * NPI function calls: 2321678453a8Sspeer * 2322678453a8Sspeer * NXGE function calls: 2323678453a8Sspeer * 2324678453a8Sspeer * Registers accessed: 2325678453a8Sspeer * 2326678453a8Sspeer * Context: 2327678453a8Sspeer * 2328678453a8Sspeer * Taking apart: 2329678453a8Sspeer * 2330678453a8Sspeer * Open questions: 2331678453a8Sspeer * 2332678453a8Sspeer */ 2333678453a8Sspeer nxge_status_t 2334678453a8Sspeer nxge_alloc_rxb( 2335678453a8Sspeer p_nxge_t nxgep, 2336678453a8Sspeer int channel) 2337678453a8Sspeer { 2338678453a8Sspeer size_t rx_buf_alloc_size; 2339678453a8Sspeer nxge_status_t status = NXGE_OK; 2340678453a8Sspeer 2341678453a8Sspeer nxge_dma_common_t **data; 2342678453a8Sspeer nxge_dma_common_t **control; 2343678453a8Sspeer uint32_t *num_chunks; 2344678453a8Sspeer 2345678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2346678453a8Sspeer 2347678453a8Sspeer /* 2348678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2349678453a8Sspeer * Replace these allocation functions with the interface functions 2350678453a8Sspeer * provided by the partition manager if/when they are available. 2351678453a8Sspeer */ 2352678453a8Sspeer 2353678453a8Sspeer /* 2354678453a8Sspeer * Allocate memory for the receive buffer blocks. 2355678453a8Sspeer */ 2356678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 23574045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2358678453a8Sspeer 2359678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2360678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2361678453a8Sspeer 2362678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2363678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2364678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2365678453a8Sspeer return (status); 236644961713Sgirish } 236744961713Sgirish 2368678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2369678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2370678453a8Sspeer 2371678453a8Sspeer /* 2372678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2373678453a8Sspeer */ 2374678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2375678453a8Sspeer 2376678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2377678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2378678453a8Sspeer != NXGE_OK) { 2379678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2380678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2381678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2382678453a8Sspeer return (status); 2383678453a8Sspeer } 238444961713Sgirish 238544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2386678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 238744961713Sgirish 238844961713Sgirish return (status); 238944961713Sgirish } 239044961713Sgirish 2391678453a8Sspeer void 2392678453a8Sspeer nxge_free_rxb( 2393678453a8Sspeer p_nxge_t nxgep, 2394678453a8Sspeer int channel) 2395678453a8Sspeer { 2396678453a8Sspeer nxge_dma_common_t *data; 2397678453a8Sspeer nxge_dma_common_t *control; 2398678453a8Sspeer uint32_t num_chunks; 2399678453a8Sspeer 2400678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2401678453a8Sspeer 2402678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2403678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2404678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2405678453a8Sspeer 2406678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2407678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2408678453a8Sspeer 2409678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2410678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2411678453a8Sspeer 2412678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2413678453a8Sspeer 2414678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2415678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2416678453a8Sspeer 2417678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2418678453a8Sspeer } 2419678453a8Sspeer 242044961713Sgirish static void 242144961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 242244961713Sgirish { 2423678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 242444961713Sgirish 242544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 242644961713Sgirish 2427678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 242844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24294045d941Ssowmini "<== nxge_free_rx_mem_pool " 24304045d941Ssowmini "(null rx buf pool or buf not allocated")); 243144961713Sgirish return; 243244961713Sgirish } 2433678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 243444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24354045d941Ssowmini "<== nxge_free_rx_mem_pool " 24364045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 243744961713Sgirish return; 243844961713Sgirish } 243944961713Sgirish 2440678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2441678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2442678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 244344961713Sgirish 2444678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2445678453a8Sspeer sizeof (uint32_t) * rdc_max); 2446678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2447678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2448678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 244944961713Sgirish 2450678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2451678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 245244961713Sgirish 2453678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2454678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2455678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2456678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2457678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2458678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2459678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2460678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2461678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 246244961713Sgirish 2463678453a8Sspeer nxgep->rx_rbr_rings = 0; 2464678453a8Sspeer nxgep->rx_rcr_rings = 0; 2465678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 246644961713Sgirish 246744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 246844961713Sgirish } 246944961713Sgirish 247044961713Sgirish 247144961713Sgirish static nxge_status_t 247244961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 247344961713Sgirish p_nxge_dma_common_t *dmap, 247444961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 247544961713Sgirish { 247644961713Sgirish p_nxge_dma_common_t rx_dmap; 247744961713Sgirish nxge_status_t status = NXGE_OK; 247844961713Sgirish size_t total_alloc_size; 247944961713Sgirish size_t allocated = 0; 248044961713Sgirish int i, size_index, array_size; 2481678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 248244961713Sgirish 248344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 248444961713Sgirish 248544961713Sgirish rx_dmap = (p_nxge_dma_common_t) 24864045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 24874045d941Ssowmini KM_SLEEP); 248844961713Sgirish 248944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24904045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 24914045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 249244961713Sgirish 249344961713Sgirish total_alloc_size = alloc_size; 249444961713Sgirish 249544961713Sgirish #if defined(RX_USE_RECLAIM_POST) 249644961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 249744961713Sgirish #endif 249844961713Sgirish 249944961713Sgirish i = 0; 250044961713Sgirish size_index = 0; 250144961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 250244961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 25034045d941Ssowmini (size_index < array_size)) 25044045d941Ssowmini size_index++; 250544961713Sgirish if (size_index >= array_size) { 250644961713Sgirish size_index = array_size - 1; 250744961713Sgirish } 250844961713Sgirish 2509678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2510678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2511678453a8Sspeer use_kmem_alloc = B_TRUE; 2512678453a8Sspeer #if defined(__i386) || defined(__amd64) 2513678453a8Sspeer size_index = 0; 2514678453a8Sspeer #endif 2515678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2516678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2517678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2518678453a8Sspeer size_index)); 2519678453a8Sspeer } 2520678453a8Sspeer 252144961713Sgirish while ((allocated < total_alloc_size) && 25224045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 252344961713Sgirish rx_dmap[i].dma_chunk_index = i; 252444961713Sgirish rx_dmap[i].block_size = block_size; 252544961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 252644961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 252744961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 252844961713Sgirish rx_dmap[i].dma_channel = dma_channel; 252944961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2530678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2531678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 253244961713Sgirish 253344961713Sgirish /* 253444961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 253544961713Sgirish * needs to call Hypervisor api to set up 253644961713Sgirish * logical pages. 253744961713Sgirish */ 253844961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 253944961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2540678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2541678453a8Sspeer } else if (use_kmem_alloc) { 2542678453a8Sspeer /* For Neptune, use kmem_alloc */ 2543678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2544678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2545678453a8Sspeer "Neptune use kmem_alloc()")); 2546678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2547678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 254844961713Sgirish } 254944961713Sgirish 255044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25514045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 25524045d941Ssowmini "i %d nblocks %d alength %d", 25534045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 25544045d941Ssowmini i, rx_dmap[i].nblocks, 25554045d941Ssowmini rx_dmap[i].alength)); 255644961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 25574045d941Ssowmini &nxge_rx_dma_attr, 25584045d941Ssowmini rx_dmap[i].alength, 25594045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 25604045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 25614045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 256244961713Sgirish if (status != NXGE_OK) { 256344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2564678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2565678453a8Sspeer "dma %d size_index %d size requested %d", 2566678453a8Sspeer dma_channel, 2567678453a8Sspeer size_index, 2568678453a8Sspeer rx_dmap[i].alength)); 256944961713Sgirish size_index--; 257044961713Sgirish } else { 2571678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2572678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2573678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2574678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2575678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2576678453a8Sspeer dma_channel, 2577678453a8Sspeer &rx_dmap[i], 2578678453a8Sspeer rx_dmap[i].kaddrp, 2579678453a8Sspeer rx_dmap[i].alength, 2580678453a8Sspeer rx_dmap[i].buf_alloc_state, 2581678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2582678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2583678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2584678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2585678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2586678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2587678453a8Sspeer rx_dmap[i].kaddrp)); 258844961713Sgirish i++; 258944961713Sgirish allocated += alloc_sizes[size_index]; 259044961713Sgirish } 259144961713Sgirish } 259244961713Sgirish 259344961713Sgirish if (allocated < total_alloc_size) { 259430ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2595678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 259630ac2e7bSml "allocated 0x%x requested 0x%x", 259730ac2e7bSml dma_channel, 259830ac2e7bSml allocated, total_alloc_size)); 259930ac2e7bSml status = NXGE_ERROR; 260044961713Sgirish goto nxge_alloc_rx_mem_fail1; 260144961713Sgirish } 260244961713Sgirish 260330ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2604678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 260530ac2e7bSml "allocated 0x%x requested 0x%x", 260630ac2e7bSml dma_channel, 260730ac2e7bSml allocated, total_alloc_size)); 260830ac2e7bSml 260944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26104045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 26114045d941Ssowmini dma_channel, i)); 261244961713Sgirish *num_chunks = i; 261344961713Sgirish *dmap = rx_dmap; 261444961713Sgirish 261544961713Sgirish goto nxge_alloc_rx_mem_exit; 261644961713Sgirish 261744961713Sgirish nxge_alloc_rx_mem_fail1: 261844961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 261944961713Sgirish 262044961713Sgirish nxge_alloc_rx_mem_exit: 262144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26224045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 262344961713Sgirish 262444961713Sgirish return (status); 262544961713Sgirish } 262644961713Sgirish 262744961713Sgirish /*ARGSUSED*/ 262844961713Sgirish static void 262944961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 263044961713Sgirish uint32_t num_chunks) 263144961713Sgirish { 263244961713Sgirish int i; 263344961713Sgirish 263444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26354045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 263644961713Sgirish 2637678453a8Sspeer if (dmap == 0) 2638678453a8Sspeer return; 2639678453a8Sspeer 264044961713Sgirish for (i = 0; i < num_chunks; i++) { 264144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26424045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 26434045d941Ssowmini i, dmap)); 2644678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 264544961713Sgirish } 264644961713Sgirish 264744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 264844961713Sgirish } 264944961713Sgirish 265044961713Sgirish /*ARGSUSED*/ 265144961713Sgirish static nxge_status_t 265244961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 265344961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 265444961713Sgirish { 265544961713Sgirish p_nxge_dma_common_t rx_dmap; 265644961713Sgirish nxge_status_t status = NXGE_OK; 265744961713Sgirish 265844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 265944961713Sgirish 266044961713Sgirish rx_dmap = (p_nxge_dma_common_t) 26614045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 266244961713Sgirish 266344961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2664678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 266544961713Sgirish 266644961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 26674045d941Ssowmini &nxge_desc_dma_attr, 26684045d941Ssowmini size, 26694045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 26704045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 26714045d941Ssowmini rx_dmap); 267244961713Sgirish if (status != NXGE_OK) { 267344961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 267444961713Sgirish } 267544961713Sgirish 267644961713Sgirish *dmap = rx_dmap; 267744961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 267844961713Sgirish 267944961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 268044961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 268144961713Sgirish 268244961713Sgirish nxge_alloc_rx_cntl_dma_exit: 268344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26844045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 268544961713Sgirish 2686678453a8Sspeer return (status); 2687678453a8Sspeer } 2688678453a8Sspeer 2689678453a8Sspeer /*ARGSUSED*/ 2690678453a8Sspeer static void 2691678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2692678453a8Sspeer { 2693678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2694678453a8Sspeer 2695678453a8Sspeer if (dmap == 0) 2696678453a8Sspeer return; 2697678453a8Sspeer 2698678453a8Sspeer nxge_dma_mem_free(dmap); 2699678453a8Sspeer 2700678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2701678453a8Sspeer } 2702678453a8Sspeer 2703678453a8Sspeer typedef struct { 2704678453a8Sspeer size_t tx_size; 2705678453a8Sspeer size_t cr_size; 2706678453a8Sspeer size_t threshhold; 2707678453a8Sspeer } nxge_tdc_sizes_t; 2708678453a8Sspeer 2709678453a8Sspeer static 2710678453a8Sspeer nxge_status_t 2711678453a8Sspeer nxge_tdc_sizes( 2712678453a8Sspeer nxge_t *nxgep, 2713678453a8Sspeer nxge_tdc_sizes_t *sizes) 2714678453a8Sspeer { 2715678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2716678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2717678453a8Sspeer size_t cr_size; /* Completion ring size */ 2718678453a8Sspeer 2719678453a8Sspeer /* 2720678453a8Sspeer * Assume that each DMA channel will be configured with the 2721678453a8Sspeer * default transmit buffer size for copying transmit data. 2722678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2723678453a8Sspeer */ 2724678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2725678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2726678453a8Sspeer } else { 2727678453a8Sspeer threshhold = nxge_bcopy_thresh; 2728678453a8Sspeer } 2729678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2730678453a8Sspeer 2731678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2732678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2733678453a8Sspeer 2734678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2735678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2736678453a8Sspeer if (!ISP2(tx_size)) { 2737678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27384045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27394045d941Ssowmini " must be power of 2")); 2740678453a8Sspeer return (NXGE_ERROR); 2741678453a8Sspeer } 2742678453a8Sspeer 2743678453a8Sspeer if (tx_size > (1 << 22)) { 2744678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27454045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27464045d941Ssowmini " limited to 4M")); 2747678453a8Sspeer return (NXGE_ERROR); 2748678453a8Sspeer } 2749678453a8Sspeer 2750678453a8Sspeer if (cr_size < 0x2000) 2751678453a8Sspeer cr_size = 0x2000; 2752678453a8Sspeer } 2753678453a8Sspeer #endif 2754678453a8Sspeer 2755678453a8Sspeer sizes->threshhold = threshhold; 2756678453a8Sspeer sizes->tx_size = tx_size; 2757678453a8Sspeer sizes->cr_size = cr_size; 2758678453a8Sspeer 2759678453a8Sspeer return (NXGE_OK); 2760678453a8Sspeer } 2761678453a8Sspeer /* 2762678453a8Sspeer * nxge_alloc_txb 2763678453a8Sspeer * 2764678453a8Sspeer * Allocate buffers for an TDC. 2765678453a8Sspeer * 2766678453a8Sspeer * Arguments: 2767678453a8Sspeer * nxgep 2768678453a8Sspeer * channel The channel to map into our kernel space. 2769678453a8Sspeer * 2770678453a8Sspeer * Notes: 2771678453a8Sspeer * 2772678453a8Sspeer * NPI function calls: 2773678453a8Sspeer * 2774678453a8Sspeer * NXGE function calls: 2775678453a8Sspeer * 2776678453a8Sspeer * Registers accessed: 2777678453a8Sspeer * 2778678453a8Sspeer * Context: 2779678453a8Sspeer * 2780678453a8Sspeer * Taking apart: 2781678453a8Sspeer * 2782678453a8Sspeer * Open questions: 2783678453a8Sspeer * 2784678453a8Sspeer */ 2785678453a8Sspeer nxge_status_t 2786678453a8Sspeer nxge_alloc_txb( 2787678453a8Sspeer p_nxge_t nxgep, 2788678453a8Sspeer int channel) 2789678453a8Sspeer { 2790678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2791678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2792678453a8Sspeer uint32_t *num_chunks; 2793678453a8Sspeer nxge_status_t status = NXGE_OK; 2794678453a8Sspeer 2795678453a8Sspeer nxge_tdc_sizes_t sizes; 2796678453a8Sspeer 2797678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2798678453a8Sspeer 2799678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2800678453a8Sspeer return (NXGE_ERROR); 2801678453a8Sspeer 2802678453a8Sspeer /* 2803678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2804678453a8Sspeer * Replace these allocation functions with the interface functions 2805678453a8Sspeer * provided by the partition manager Real Soon Now. 2806678453a8Sspeer */ 2807678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2808678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2809678453a8Sspeer 2810678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2811678453a8Sspeer 2812678453a8Sspeer /* 2813678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2814678453a8Sspeer * Replace allocation functions with interface functions provided 2815678453a8Sspeer * by the partition manager when it is available. 2816678453a8Sspeer * 2817678453a8Sspeer * Allocate memory for the transmit buffer pool. 2818678453a8Sspeer */ 2819678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28204045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 28214045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2822678453a8Sspeer 2823678453a8Sspeer *num_chunks = 0; 2824678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2825678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2826678453a8Sspeer if (status != NXGE_OK) { 2827678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2828678453a8Sspeer return (status); 2829678453a8Sspeer } 2830678453a8Sspeer 2831678453a8Sspeer /* 2832678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2833678453a8Sspeer */ 2834678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2835678453a8Sspeer sizes.cr_size); 2836678453a8Sspeer if (status != NXGE_OK) { 2837678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2838678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2839678453a8Sspeer return (status); 2840678453a8Sspeer } 2841678453a8Sspeer 2842678453a8Sspeer return (NXGE_OK); 2843678453a8Sspeer } 2844678453a8Sspeer 2845678453a8Sspeer void 2846678453a8Sspeer nxge_free_txb( 2847678453a8Sspeer p_nxge_t nxgep, 2848678453a8Sspeer int channel) 2849678453a8Sspeer { 2850678453a8Sspeer nxge_dma_common_t *data; 2851678453a8Sspeer nxge_dma_common_t *control; 2852678453a8Sspeer uint32_t num_chunks; 2853678453a8Sspeer 2854678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2855678453a8Sspeer 2856678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2857678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2858678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2859678453a8Sspeer 2860678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2861678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2862678453a8Sspeer 2863678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2864678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 286544961713Sgirish 2866678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 286744961713Sgirish 2868678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2869678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 287044961713Sgirish 2871678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 287244961713Sgirish } 287344961713Sgirish 2874678453a8Sspeer /* 2875678453a8Sspeer * nxge_alloc_tx_mem_pool 2876678453a8Sspeer * 2877678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2878678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2879678453a8Sspeer * 2880678453a8Sspeer * Arguments: 2881678453a8Sspeer * nxgep 2882678453a8Sspeer * 2883678453a8Sspeer * Notes: 2884678453a8Sspeer * 2885678453a8Sspeer * Context: 2886678453a8Sspeer * Any domain 2887678453a8Sspeer */ 2888678453a8Sspeer nxge_status_t 288944961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 289044961713Sgirish { 2891678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 2892678453a8Sspeer nxge_dma_pool_t *dma_poolp; 2893678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2894678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 2895678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 289644961713Sgirish uint32_t *num_chunks; /* per dma */ 2897678453a8Sspeer int tdc_max; 289844961713Sgirish 289944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 290044961713Sgirish 2901678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 2902678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 290344961713Sgirish 290444961713Sgirish /* 290544961713Sgirish * Allocate memory for each transmit DMA channel. 290644961713Sgirish */ 290744961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 29084045d941Ssowmini KM_SLEEP); 290944961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29104045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 291144961713Sgirish 291244961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 29134045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 291444961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29154045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 291644961713Sgirish 291730ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 291830ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 291930ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 292030ac2e7bSml "set to default %d", 292130ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 292230ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 292330ac2e7bSml } 292430ac2e7bSml 292544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 292644961713Sgirish /* 292744961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 292844961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 292944961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 293044961713Sgirish * function). The transmit ring is limited to 8K (includes the 293144961713Sgirish * mailbox). 293244961713Sgirish */ 293344961713Sgirish if (nxgep->niu_type == N2_NIU) { 293444961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 29354045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 293644961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 293744961713Sgirish } 293844961713Sgirish } 293944961713Sgirish #endif 294044961713Sgirish 294144961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 294244961713Sgirish 294344961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 29444045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 294544961713Sgirish 2946678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 294744961713Sgirish dma_poolp->num_chunks = num_chunks; 294844961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 294944961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 295044961713Sgirish 2951678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 2952678453a8Sspeer 2953678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 295444961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 295544961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 295644961713Sgirish 2957678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 295844961713Sgirish 2959678453a8Sspeer nxgep->tx_rings = 2960678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 2961678453a8Sspeer nxgep->tx_rings->rings = 2962678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 2963678453a8Sspeer nxgep->tx_mbox_areas_p = 2964678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 2965678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 2966678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 296744961713Sgirish 2968678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 296944961713Sgirish 297044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 29714045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 29724045d941Ssowmini tdc_max, dma_poolp->ndmas)); 297344961713Sgirish 2974678453a8Sspeer return (NXGE_OK); 297544961713Sgirish } 297644961713Sgirish 2977678453a8Sspeer nxge_status_t 297844961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 297944961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 298044961713Sgirish size_t block_size, uint32_t *num_chunks) 298144961713Sgirish { 298244961713Sgirish p_nxge_dma_common_t tx_dmap; 298344961713Sgirish nxge_status_t status = NXGE_OK; 298444961713Sgirish size_t total_alloc_size; 298544961713Sgirish size_t allocated = 0; 298644961713Sgirish int i, size_index, array_size; 298744961713Sgirish 298844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 298944961713Sgirish 299044961713Sgirish tx_dmap = (p_nxge_dma_common_t) 29914045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 29924045d941Ssowmini KM_SLEEP); 299344961713Sgirish 299444961713Sgirish total_alloc_size = alloc_size; 299544961713Sgirish i = 0; 299644961713Sgirish size_index = 0; 299744961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 299844961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 29994045d941Ssowmini (size_index < array_size)) 300044961713Sgirish size_index++; 300144961713Sgirish if (size_index >= array_size) { 300244961713Sgirish size_index = array_size - 1; 300344961713Sgirish } 300444961713Sgirish 300544961713Sgirish while ((allocated < total_alloc_size) && 30064045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 300744961713Sgirish 300844961713Sgirish tx_dmap[i].dma_chunk_index = i; 300944961713Sgirish tx_dmap[i].block_size = block_size; 301044961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 301144961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 301244961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 301344961713Sgirish tx_dmap[i].dma_channel = dma_channel; 301444961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3015678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 301644961713Sgirish 301744961713Sgirish /* 301844961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 301944961713Sgirish * needs to call Hypervisor api to set up 302044961713Sgirish * logical pages. 302144961713Sgirish */ 302244961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 302344961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 302444961713Sgirish } 302544961713Sgirish 302644961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 30274045d941Ssowmini &nxge_tx_dma_attr, 30284045d941Ssowmini tx_dmap[i].alength, 30294045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 30304045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 30314045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 303244961713Sgirish if (status != NXGE_OK) { 303344961713Sgirish size_index--; 303444961713Sgirish } else { 303544961713Sgirish i++; 303644961713Sgirish allocated += alloc_sizes[size_index]; 303744961713Sgirish } 303844961713Sgirish } 303944961713Sgirish 304044961713Sgirish if (allocated < total_alloc_size) { 304130ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 304230ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 304330ac2e7bSml "allocated 0x%x requested 0x%x", 304430ac2e7bSml dma_channel, 304530ac2e7bSml allocated, total_alloc_size)); 304630ac2e7bSml status = NXGE_ERROR; 304744961713Sgirish goto nxge_alloc_tx_mem_fail1; 304844961713Sgirish } 304944961713Sgirish 305030ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 305130ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 305230ac2e7bSml "allocated 0x%x requested 0x%x", 305330ac2e7bSml dma_channel, 305430ac2e7bSml allocated, total_alloc_size)); 305530ac2e7bSml 305644961713Sgirish *num_chunks = i; 305744961713Sgirish *dmap = tx_dmap; 305844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 30594045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 30604045d941Ssowmini *dmap, i)); 306144961713Sgirish goto nxge_alloc_tx_mem_exit; 306244961713Sgirish 306344961713Sgirish nxge_alloc_tx_mem_fail1: 306444961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 306544961713Sgirish 306644961713Sgirish nxge_alloc_tx_mem_exit: 306744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 30684045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 306944961713Sgirish 307044961713Sgirish return (status); 307144961713Sgirish } 307244961713Sgirish 307344961713Sgirish /*ARGSUSED*/ 307444961713Sgirish static void 307544961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 307644961713Sgirish uint32_t num_chunks) 307744961713Sgirish { 307844961713Sgirish int i; 307944961713Sgirish 308044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 308144961713Sgirish 3082678453a8Sspeer if (dmap == 0) 3083678453a8Sspeer return; 3084678453a8Sspeer 308544961713Sgirish for (i = 0; i < num_chunks; i++) { 308644961713Sgirish nxge_dma_mem_free(dmap++); 308744961713Sgirish } 308844961713Sgirish 308944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 309044961713Sgirish } 309144961713Sgirish 309244961713Sgirish /*ARGSUSED*/ 3093678453a8Sspeer nxge_status_t 309444961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 309544961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 309644961713Sgirish { 309744961713Sgirish p_nxge_dma_common_t tx_dmap; 309844961713Sgirish nxge_status_t status = NXGE_OK; 309944961713Sgirish 310044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 310144961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31024045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 310344961713Sgirish 310444961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3105678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 310644961713Sgirish 310744961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31084045d941Ssowmini &nxge_desc_dma_attr, 31094045d941Ssowmini size, 31104045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 31114045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 31124045d941Ssowmini tx_dmap); 311344961713Sgirish if (status != NXGE_OK) { 311444961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 311544961713Sgirish } 311644961713Sgirish 311744961713Sgirish *dmap = tx_dmap; 311844961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 311944961713Sgirish 312044961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 312144961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 312244961713Sgirish 312344961713Sgirish nxge_alloc_tx_cntl_dma_exit: 312444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31254045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 312644961713Sgirish 312744961713Sgirish return (status); 312844961713Sgirish } 312944961713Sgirish 313044961713Sgirish /*ARGSUSED*/ 313144961713Sgirish static void 313244961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 313344961713Sgirish { 313444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 313544961713Sgirish 3136678453a8Sspeer if (dmap == 0) 3137678453a8Sspeer return; 3138678453a8Sspeer 313944961713Sgirish nxge_dma_mem_free(dmap); 314044961713Sgirish 314144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 314244961713Sgirish } 314344961713Sgirish 3144678453a8Sspeer /* 3145678453a8Sspeer * nxge_free_tx_mem_pool 3146678453a8Sspeer * 3147678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3148678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3149678453a8Sspeer * is stopped. 3150678453a8Sspeer * 3151678453a8Sspeer * Arguments: 3152678453a8Sspeer * nxgep 3153678453a8Sspeer * 3154678453a8Sspeer * Notes: 3155678453a8Sspeer * 3156678453a8Sspeer * Context: 3157678453a8Sspeer * Any domain 3158678453a8Sspeer */ 315944961713Sgirish static void 316044961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 316144961713Sgirish { 3162678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 316344961713Sgirish 3164678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 316544961713Sgirish 3166678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3167678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 31684045d941Ssowmini "<== nxge_free_tx_mem_pool " 31694045d941Ssowmini "(null tx buf pool or buf not allocated")); 317044961713Sgirish return; 317144961713Sgirish } 3172678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3173678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 31744045d941Ssowmini "<== nxge_free_tx_mem_pool " 31754045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 317644961713Sgirish return; 317744961713Sgirish } 317844961713Sgirish 3179678453a8Sspeer /* 1. Free the mailboxes. */ 3180678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3181678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3182678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 318344961713Sgirish 3184678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 318544961713Sgirish 3186678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3187678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3188678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3189678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 319044961713Sgirish 3191678453a8Sspeer nxgep->tx_rings = 0; 319244961713Sgirish 3193678453a8Sspeer /* 3. Free the completion ring data structures. */ 3194678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3195678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3196678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 319744961713Sgirish 3198678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 319944961713Sgirish 3200678453a8Sspeer /* 4. Free the data ring data structures. */ 3201678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3202678453a8Sspeer sizeof (uint32_t) * tdc_max); 3203678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3204678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3205678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 320644961713Sgirish 3207678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3208678453a8Sspeer 3209678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 321044961713Sgirish } 321144961713Sgirish 321244961713Sgirish /*ARGSUSED*/ 321344961713Sgirish static nxge_status_t 321444961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 321544961713Sgirish struct ddi_dma_attr *dma_attrp, 321644961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 321744961713Sgirish p_nxge_dma_common_t dma_p) 321844961713Sgirish { 321944961713Sgirish caddr_t kaddrp; 322044961713Sgirish int ddi_status = DDI_SUCCESS; 322144961713Sgirish boolean_t contig_alloc_type; 3222678453a8Sspeer boolean_t kmem_alloc_type; 322344961713Sgirish 322444961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 322544961713Sgirish 322644961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 322744961713Sgirish /* 322844961713Sgirish * contig_alloc_type for contiguous memory only allowed 322944961713Sgirish * for N2/NIU. 323044961713Sgirish */ 323144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32324045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 32334045d941Ssowmini dma_p->contig_alloc_type)); 323444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 323544961713Sgirish } 323644961713Sgirish 323744961713Sgirish dma_p->dma_handle = NULL; 323844961713Sgirish dma_p->acc_handle = NULL; 323944961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 324044961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 324144961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 32424045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 324344961713Sgirish if (ddi_status != DDI_SUCCESS) { 324444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32454045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 324644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 324744961713Sgirish } 324844961713Sgirish 3249678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3250678453a8Sspeer 325144961713Sgirish switch (contig_alloc_type) { 325244961713Sgirish case B_FALSE: 3253678453a8Sspeer switch (kmem_alloc_type) { 3254678453a8Sspeer case B_FALSE: 3255678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 32564045d941Ssowmini length, 32574045d941Ssowmini acc_attr_p, 32584045d941Ssowmini xfer_flags, 32594045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 32604045d941Ssowmini &dma_p->acc_handle); 3261678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3262678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3263678453a8Sspeer "nxge_dma_mem_alloc: " 3264678453a8Sspeer "ddi_dma_mem_alloc failed")); 3265678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3266678453a8Sspeer dma_p->dma_handle = NULL; 3267678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3268678453a8Sspeer } 3269678453a8Sspeer if (dma_p->alength < length) { 3270678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3271678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3272678453a8Sspeer "< length.")); 327344961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3274678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 327544961713Sgirish dma_p->acc_handle = NULL; 3276678453a8Sspeer dma_p->dma_handle = NULL; 3277678453a8Sspeer return (NXGE_ERROR); 327844961713Sgirish } 327944961713Sgirish 3280678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3281678453a8Sspeer NULL, 3282678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3283678453a8Sspeer DDI_DMA_DONTWAIT, 3284678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3285678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3286678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3287678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3288678453a8Sspeer "failed " 3289678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3290678453a8Sspeer dma_p->ncookies)); 3291678453a8Sspeer if (dma_p->acc_handle) { 3292678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3293678453a8Sspeer dma_p->acc_handle = NULL; 3294678453a8Sspeer } 3295678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3296678453a8Sspeer dma_p->dma_handle = NULL; 3297678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3298678453a8Sspeer } 3299678453a8Sspeer 3300678453a8Sspeer if (dma_p->ncookies != 1) { 3301678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3302678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3303678453a8Sspeer "> 1 cookie" 3304678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3305678453a8Sspeer dma_p->ncookies)); 3306678453a8Sspeer if (dma_p->acc_handle) { 3307678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3308678453a8Sspeer dma_p->acc_handle = NULL; 3309678453a8Sspeer } 3310678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3311678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3312678453a8Sspeer dma_p->dma_handle = NULL; 3313678453a8Sspeer return (NXGE_ERROR); 3314678453a8Sspeer } 3315678453a8Sspeer break; 3316678453a8Sspeer 3317678453a8Sspeer case B_TRUE: 3318678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3319678453a8Sspeer if (kaddrp == NULL) { 3320678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3321678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3322678453a8Sspeer "kmem alloc failed")); 3323678453a8Sspeer return (NXGE_ERROR); 3324678453a8Sspeer } 3325678453a8Sspeer 3326678453a8Sspeer dma_p->alength = length; 3327678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3328678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3329678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3330678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3331678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3332678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3333678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3334678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3335678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3336678453a8Sspeer kaddrp, length, 3337678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3338678453a8Sspeer KMEM_FREE(kaddrp, length); 3339678453a8Sspeer dma_p->acc_handle = NULL; 3340678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3341678453a8Sspeer dma_p->dma_handle = NULL; 3342678453a8Sspeer dma_p->kaddrp = NULL; 3343678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3344678453a8Sspeer } 3345678453a8Sspeer 3346678453a8Sspeer if (dma_p->ncookies != 1) { 3347678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3348678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3349678453a8Sspeer "(kmem_alloc) > 1 cookie" 3350678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 33514045d941Ssowmini dma_p->ncookies)); 3352678453a8Sspeer KMEM_FREE(kaddrp, length); 335344961713Sgirish dma_p->acc_handle = NULL; 3354678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3355678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3356678453a8Sspeer dma_p->dma_handle = NULL; 3357678453a8Sspeer dma_p->kaddrp = NULL; 3358678453a8Sspeer return (NXGE_ERROR); 335944961713Sgirish } 3360678453a8Sspeer 3361678453a8Sspeer dma_p->kaddrp = kaddrp; 3362678453a8Sspeer 3363678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 33644045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 33654045d941Ssowmini "kaddr $%p alength %d", 33664045d941Ssowmini dma_p, 33674045d941Ssowmini kaddrp, 33684045d941Ssowmini dma_p->alength)); 3369678453a8Sspeer break; 337044961713Sgirish } 337144961713Sgirish break; 337244961713Sgirish 337344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 337444961713Sgirish case B_TRUE: 337544961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 337644961713Sgirish if (kaddrp == NULL) { 337744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33784045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 337944961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 338044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 338144961713Sgirish } 338244961713Sgirish 338344961713Sgirish dma_p->alength = length; 338444961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 33854045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 33864045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 338744961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 338844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33894045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 33904045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 33914045d941Ssowmini dma_p->ncookies)); 339244961713Sgirish 339344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 33944045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 33954045d941Ssowmini "length %lu (0x%x) " 33964045d941Ssowmini "free contig kaddrp $%p " 33974045d941Ssowmini "va_to_pa $%p", 33984045d941Ssowmini length, length, 33994045d941Ssowmini kaddrp, 34004045d941Ssowmini va_to_pa(kaddrp))); 340144961713Sgirish 340244961713Sgirish 340344961713Sgirish contig_mem_free((void *)kaddrp, length); 340444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 340544961713Sgirish 340644961713Sgirish dma_p->dma_handle = NULL; 340744961713Sgirish dma_p->acc_handle = NULL; 340844961713Sgirish dma_p->alength = NULL; 340944961713Sgirish dma_p->kaddrp = NULL; 341044961713Sgirish 341144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 341244961713Sgirish } 341344961713Sgirish 341444961713Sgirish if (dma_p->ncookies != 1 || 34154045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 341644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34174045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 34184045d941Ssowmini "cookie or " 34194045d941Ssowmini "dmac_laddress is NULL $%p size %d " 34204045d941Ssowmini " (status 0x%x ncookies %d.)", 34214045d941Ssowmini ddi_status, 34224045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 34234045d941Ssowmini dma_p->dma_cookie.dmac_size, 34244045d941Ssowmini dma_p->ncookies)); 342544961713Sgirish 342644961713Sgirish contig_mem_free((void *)kaddrp, length); 342756d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 342844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 342944961713Sgirish 343044961713Sgirish dma_p->alength = 0; 343144961713Sgirish dma_p->dma_handle = NULL; 343244961713Sgirish dma_p->acc_handle = NULL; 343344961713Sgirish dma_p->kaddrp = NULL; 343444961713Sgirish 343544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 343644961713Sgirish } 343744961713Sgirish break; 343844961713Sgirish 343944961713Sgirish #else 344044961713Sgirish case B_TRUE: 344144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34424045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 344344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 344444961713Sgirish #endif 344544961713Sgirish } 344644961713Sgirish 344744961713Sgirish dma_p->kaddrp = kaddrp; 344844961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 34494045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3450adfcba55Sjoycey #if defined(__i386) 3451adfcba55Sjoycey dma_p->ioaddr_pp = 34524045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3453adfcba55Sjoycey #else 345444961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3455adfcba55Sjoycey #endif 345644961713Sgirish dma_p->last_ioaddr_pp = 3457adfcba55Sjoycey #if defined(__i386) 34584045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3459adfcba55Sjoycey #else 34604045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3461adfcba55Sjoycey #endif 34624045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 346344961713Sgirish 346444961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 346544961713Sgirish 346644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 346744961713Sgirish dma_p->orig_ioaddr_pp = 34684045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 346944961713Sgirish dma_p->orig_alength = length; 347044961713Sgirish dma_p->orig_kaddrp = kaddrp; 347144961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 347244961713Sgirish #endif 347344961713Sgirish 347444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 34754045d941Ssowmini "dma buffer allocated: dma_p $%p " 34764045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 34774045d941Ssowmini "dma_p->ioaddr_p $%p " 34784045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 34794045d941Ssowmini "orig_vatopa $%p " 34804045d941Ssowmini "alength %d (0x%x) " 34814045d941Ssowmini "kaddrp $%p " 34824045d941Ssowmini "length %d (0x%x)", 34834045d941Ssowmini dma_p, 34844045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 34854045d941Ssowmini dma_p->ioaddr_pp, 34864045d941Ssowmini dma_p->orig_ioaddr_pp, 34874045d941Ssowmini dma_p->orig_vatopa, 34884045d941Ssowmini dma_p->alength, dma_p->alength, 34894045d941Ssowmini kaddrp, 34904045d941Ssowmini length, length)); 349144961713Sgirish 349244961713Sgirish return (NXGE_OK); 349344961713Sgirish } 349444961713Sgirish 349544961713Sgirish static void 349644961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 349744961713Sgirish { 349844961713Sgirish if (dma_p->dma_handle != NULL) { 349944961713Sgirish if (dma_p->ncookies) { 350044961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 350144961713Sgirish dma_p->ncookies = 0; 350244961713Sgirish } 350344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 350444961713Sgirish dma_p->dma_handle = NULL; 350544961713Sgirish } 350644961713Sgirish 350744961713Sgirish if (dma_p->acc_handle != NULL) { 350844961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 350944961713Sgirish dma_p->acc_handle = NULL; 351044961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 351144961713Sgirish } 351244961713Sgirish 351344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 351444961713Sgirish if (dma_p->contig_alloc_type && 35154045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 351644961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 35174045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 35184045d941Ssowmini "mem type %d ", 35194045d941Ssowmini "orig_alength %d " 35204045d941Ssowmini "alength 0x%x (%d)", 35214045d941Ssowmini dma_p->kaddrp, 35224045d941Ssowmini dma_p->orig_kaddrp, 35234045d941Ssowmini dma_p->contig_alloc_type, 35244045d941Ssowmini dma_p->orig_alength, 35254045d941Ssowmini dma_p->alength, dma_p->alength)); 352644961713Sgirish 352744961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 352844961713Sgirish dma_p->orig_alength = NULL; 352944961713Sgirish dma_p->orig_kaddrp = NULL; 353044961713Sgirish dma_p->contig_alloc_type = B_FALSE; 353144961713Sgirish } 353244961713Sgirish #endif 353344961713Sgirish dma_p->kaddrp = NULL; 353444961713Sgirish dma_p->alength = NULL; 353544961713Sgirish } 353644961713Sgirish 3537678453a8Sspeer static void 3538678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3539678453a8Sspeer { 3540678453a8Sspeer uint64_t kaddr; 3541678453a8Sspeer uint32_t buf_size; 3542678453a8Sspeer 3543678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3544678453a8Sspeer 3545678453a8Sspeer if (dma_p->dma_handle != NULL) { 3546678453a8Sspeer if (dma_p->ncookies) { 3547678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3548678453a8Sspeer dma_p->ncookies = 0; 3549678453a8Sspeer } 3550678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3551678453a8Sspeer dma_p->dma_handle = NULL; 3552678453a8Sspeer } 3553678453a8Sspeer 3554678453a8Sspeer if (dma_p->acc_handle != NULL) { 3555678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3556678453a8Sspeer dma_p->acc_handle = NULL; 3557678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3558678453a8Sspeer } 3559678453a8Sspeer 3560678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3561678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3562678453a8Sspeer dma_p, 3563678453a8Sspeer dma_p->buf_alloc_state)); 3564678453a8Sspeer 3565678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3566678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3567678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3568678453a8Sspeer "outstanding data buffers")); 3569678453a8Sspeer return; 3570678453a8Sspeer } 3571678453a8Sspeer 3572678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3573678453a8Sspeer if (dma_p->contig_alloc_type && 35744045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3575678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3576678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3577678453a8Sspeer "mem type %d ", 3578678453a8Sspeer "orig_alength %d " 3579678453a8Sspeer "alength 0x%x (%d)", 3580678453a8Sspeer dma_p->kaddrp, 3581678453a8Sspeer dma_p->orig_kaddrp, 3582678453a8Sspeer dma_p->contig_alloc_type, 3583678453a8Sspeer dma_p->orig_alength, 3584678453a8Sspeer dma_p->alength, dma_p->alength)); 3585678453a8Sspeer 3586678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3587678453a8Sspeer buf_size = dma_p->orig_alength; 3588678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3589678453a8Sspeer dma_p->orig_alength = NULL; 3590678453a8Sspeer dma_p->orig_kaddrp = NULL; 3591678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3592678453a8Sspeer dma_p->kaddrp = NULL; 3593678453a8Sspeer dma_p->alength = NULL; 3594678453a8Sspeer return; 3595678453a8Sspeer } 3596678453a8Sspeer #endif 3597678453a8Sspeer 3598678453a8Sspeer if (dma_p->kmem_alloc_type) { 3599678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3600678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 36014045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36024045d941Ssowmini "alloc type %d " 36034045d941Ssowmini "orig_alength %d " 36044045d941Ssowmini "alength 0x%x (%d)", 36054045d941Ssowmini dma_p->kaddrp, 36064045d941Ssowmini dma_p->orig_kaddrp, 36074045d941Ssowmini dma_p->kmem_alloc_type, 36084045d941Ssowmini dma_p->orig_alength, 36094045d941Ssowmini dma_p->alength, dma_p->alength)); 3610678453a8Sspeer #if defined(__i386) 3611678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3612678453a8Sspeer #else 3613678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3614678453a8Sspeer #endif 3615678453a8Sspeer buf_size = dma_p->orig_alength; 3616678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3617678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3618678453a8Sspeer "kaddr $%p buf_size %d", 3619678453a8Sspeer dma_p, 3620678453a8Sspeer kaddr, buf_size)); 3621678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3622678453a8Sspeer dma_p->alength = 0; 3623678453a8Sspeer dma_p->orig_alength = 0; 3624678453a8Sspeer dma_p->kaddrp = NULL; 3625678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3626678453a8Sspeer } 3627678453a8Sspeer 3628678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3629678453a8Sspeer } 3630678453a8Sspeer 363144961713Sgirish /* 363244961713Sgirish * nxge_m_start() -- start transmitting and receiving. 363344961713Sgirish * 363444961713Sgirish * This function is called by the MAC layer when the first 363544961713Sgirish * stream is open to prepare the hardware ready for sending 363644961713Sgirish * and transmitting packets. 363744961713Sgirish */ 363844961713Sgirish static int 363944961713Sgirish nxge_m_start(void *arg) 364044961713Sgirish { 364144961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 364244961713Sgirish 364344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 364444961713Sgirish 3645*6f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 3646*6f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 3647*6f157acbSml } 3648*6f157acbSml 364944961713Sgirish MUTEX_ENTER(nxgep->genlock); 365014ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 365144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 36524045d941Ssowmini "<== nxge_m_start: initialization failed")); 365344961713Sgirish MUTEX_EXIT(nxgep->genlock); 365444961713Sgirish return (EIO); 365544961713Sgirish } 365644961713Sgirish 365714ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 365814ea4bb7Ssd goto nxge_m_start_exit; 365944961713Sgirish /* 366044961713Sgirish * Start timer to check the system error and tx hangs 366144961713Sgirish */ 3662678453a8Sspeer if (!isLDOMguest(nxgep)) 3663678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3664678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3665678453a8Sspeer #if defined(sun4v) 3666678453a8Sspeer else 3667678453a8Sspeer nxge_hio_start_timer(nxgep); 3668678453a8Sspeer #endif 366944961713Sgirish 3670a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3671a3c5bd6dSspeer 367244961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 367344961713Sgirish 367414ea4bb7Ssd nxge_m_start_exit: 367544961713Sgirish MUTEX_EXIT(nxgep->genlock); 367644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 367744961713Sgirish return (0); 367844961713Sgirish } 367944961713Sgirish 368044961713Sgirish /* 368144961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 368244961713Sgirish */ 368344961713Sgirish static void 368444961713Sgirish nxge_m_stop(void *arg) 368544961713Sgirish { 368644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 368744961713Sgirish 368844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 368944961713Sgirish 369044961713Sgirish if (nxgep->nxge_timerid) { 369144961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 369244961713Sgirish nxgep->nxge_timerid = 0; 369344961713Sgirish } 3694a3c5bd6dSspeer 3695a3c5bd6dSspeer MUTEX_ENTER(nxgep->genlock); 3696678453a8Sspeer nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 369744961713Sgirish nxge_uninit(nxgep); 369844961713Sgirish 369944961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 370044961713Sgirish 370144961713Sgirish MUTEX_EXIT(nxgep->genlock); 370244961713Sgirish 370344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 370444961713Sgirish } 370544961713Sgirish 370644961713Sgirish static int 370744961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr) 370844961713Sgirish { 370944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 371044961713Sgirish struct ether_addr addrp; 371144961713Sgirish 371244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst")); 371344961713Sgirish 371444961713Sgirish bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 371544961713Sgirish if (nxge_set_mac_addr(nxgep, &addrp)) { 371644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37174045d941Ssowmini "<== nxge_m_unicst: set unitcast failed")); 371844961713Sgirish return (EINVAL); 371944961713Sgirish } 372044961713Sgirish 372144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst")); 372244961713Sgirish 372344961713Sgirish return (0); 372444961713Sgirish } 372544961713Sgirish 372644961713Sgirish static int 372744961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 372844961713Sgirish { 372944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 373044961713Sgirish struct ether_addr addrp; 373144961713Sgirish 373244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37334045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 373444961713Sgirish 373544961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 373644961713Sgirish if (add) { 373744961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 373844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37394045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 374044961713Sgirish return (EINVAL); 374144961713Sgirish } 374244961713Sgirish } else { 374344961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 374444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37454045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 374644961713Sgirish return (EINVAL); 374744961713Sgirish } 374844961713Sgirish } 374944961713Sgirish 375044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 375144961713Sgirish 375244961713Sgirish return (0); 375344961713Sgirish } 375444961713Sgirish 375544961713Sgirish static int 375644961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 375744961713Sgirish { 375844961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 375944961713Sgirish 376044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37614045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 376244961713Sgirish 376344961713Sgirish if (nxge_set_promisc(nxgep, on)) { 376444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37654045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 376644961713Sgirish return (EINVAL); 376744961713Sgirish } 376844961713Sgirish 376944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37704045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 377144961713Sgirish 377244961713Sgirish return (0); 377344961713Sgirish } 377444961713Sgirish 377544961713Sgirish static void 377644961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 377744961713Sgirish { 377844961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 377956d930aeSspeer struct iocblk *iocp; 378044961713Sgirish boolean_t need_privilege; 378144961713Sgirish int err; 378244961713Sgirish int cmd; 378344961713Sgirish 378444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 378544961713Sgirish 378644961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 378744961713Sgirish iocp->ioc_error = 0; 378844961713Sgirish need_privilege = B_TRUE; 378944961713Sgirish cmd = iocp->ioc_cmd; 379044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 379144961713Sgirish switch (cmd) { 379244961713Sgirish default: 379344961713Sgirish miocnak(wq, mp, 0, EINVAL); 379444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 379544961713Sgirish return; 379644961713Sgirish 379744961713Sgirish case LB_GET_INFO_SIZE: 379844961713Sgirish case LB_GET_INFO: 379944961713Sgirish case LB_GET_MODE: 380044961713Sgirish need_privilege = B_FALSE; 380144961713Sgirish break; 380244961713Sgirish case LB_SET_MODE: 380344961713Sgirish break; 380444961713Sgirish 380544961713Sgirish 380644961713Sgirish case NXGE_GET_MII: 380744961713Sgirish case NXGE_PUT_MII: 380844961713Sgirish case NXGE_GET64: 380944961713Sgirish case NXGE_PUT64: 381044961713Sgirish case NXGE_GET_TX_RING_SZ: 381144961713Sgirish case NXGE_GET_TX_DESC: 381244961713Sgirish case NXGE_TX_SIDE_RESET: 381344961713Sgirish case NXGE_RX_SIDE_RESET: 381444961713Sgirish case NXGE_GLOBAL_RESET: 381544961713Sgirish case NXGE_RESET_MAC: 381644961713Sgirish case NXGE_TX_REGS_DUMP: 381744961713Sgirish case NXGE_RX_REGS_DUMP: 381844961713Sgirish case NXGE_INT_REGS_DUMP: 381944961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 382044961713Sgirish case NXGE_PUT_TCAM: 382144961713Sgirish case NXGE_GET_TCAM: 382244961713Sgirish case NXGE_RTRACE: 382344961713Sgirish case NXGE_RDUMP: 382444961713Sgirish 382544961713Sgirish need_privilege = B_FALSE; 382644961713Sgirish break; 382744961713Sgirish case NXGE_INJECT_ERR: 382844961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 382944961713Sgirish nxge_err_inject(nxgep, wq, mp); 383044961713Sgirish break; 383144961713Sgirish } 383244961713Sgirish 383344961713Sgirish if (need_privilege) { 383456d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 383544961713Sgirish if (err != 0) { 383644961713Sgirish miocnak(wq, mp, 0, err); 383744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38384045d941Ssowmini "<== nxge_m_ioctl: no priv")); 383944961713Sgirish return; 384044961713Sgirish } 384144961713Sgirish } 384244961713Sgirish 384344961713Sgirish switch (cmd) { 384444961713Sgirish 384544961713Sgirish case LB_GET_MODE: 384644961713Sgirish case LB_SET_MODE: 384744961713Sgirish case LB_GET_INFO_SIZE: 384844961713Sgirish case LB_GET_INFO: 384944961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 385044961713Sgirish break; 385144961713Sgirish 385244961713Sgirish case NXGE_GET_MII: 385344961713Sgirish case NXGE_PUT_MII: 385444961713Sgirish case NXGE_PUT_TCAM: 385544961713Sgirish case NXGE_GET_TCAM: 385644961713Sgirish case NXGE_GET64: 385744961713Sgirish case NXGE_PUT64: 385844961713Sgirish case NXGE_GET_TX_RING_SZ: 385944961713Sgirish case NXGE_GET_TX_DESC: 386044961713Sgirish case NXGE_TX_SIDE_RESET: 386144961713Sgirish case NXGE_RX_SIDE_RESET: 386244961713Sgirish case NXGE_GLOBAL_RESET: 386344961713Sgirish case NXGE_RESET_MAC: 386444961713Sgirish case NXGE_TX_REGS_DUMP: 386544961713Sgirish case NXGE_RX_REGS_DUMP: 386644961713Sgirish case NXGE_INT_REGS_DUMP: 386744961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 386844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 38694045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 387044961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 387144961713Sgirish break; 387244961713Sgirish } 387344961713Sgirish 387444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 387544961713Sgirish } 387644961713Sgirish 387744961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 387844961713Sgirish 387944961713Sgirish static void 388044961713Sgirish nxge_m_resources(void *arg) 388144961713Sgirish { 388244961713Sgirish p_nxge_t nxgep = arg; 388344961713Sgirish mac_rx_fifo_t mrf; 3884678453a8Sspeer 3885678453a8Sspeer nxge_grp_set_t *set = &nxgep->rx_set; 3886678453a8Sspeer uint8_t rdc; 3887678453a8Sspeer 3888678453a8Sspeer rx_rcr_ring_t *ring; 388944961713Sgirish 389044961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources")); 389144961713Sgirish 389244961713Sgirish MUTEX_ENTER(nxgep->genlock); 389314ea4bb7Ssd 3894678453a8Sspeer if (set->owned.map == 0) { 3895678453a8Sspeer NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 3896678453a8Sspeer "nxge_m_resources: no receive resources")); 3897678453a8Sspeer goto nxge_m_resources_exit; 3898678453a8Sspeer } 3899678453a8Sspeer 390014ea4bb7Ssd /* 390158324dfcSspeer * CR 6492541 Check to see if the drv_state has been initialized, 390214ea4bb7Ssd * if not * call nxge_init(). 390314ea4bb7Ssd */ 390414ea4bb7Ssd if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 3905678453a8Sspeer if (nxge_init(nxgep) != NXGE_OK) 390614ea4bb7Ssd goto nxge_m_resources_exit; 390714ea4bb7Ssd } 390814ea4bb7Ssd 390944961713Sgirish mrf.mrf_type = MAC_RX_FIFO; 391044961713Sgirish mrf.mrf_blank = nxge_rx_hw_blank; 391144961713Sgirish mrf.mrf_arg = (void *)nxgep; 391244961713Sgirish 391344961713Sgirish mrf.mrf_normal_blank_time = 128; 391444961713Sgirish mrf.mrf_normal_pkt_count = 8; 391544961713Sgirish 391614ea4bb7Ssd /* 391714ea4bb7Ssd * Export our receive resources to the MAC layer. 391814ea4bb7Ssd */ 3919678453a8Sspeer for (rdc = 0; rdc < NXGE_MAX_RDCS; rdc++) { 3920678453a8Sspeer if ((1 << rdc) & set->owned.map) { 3921678453a8Sspeer ring = nxgep->rx_rcr_rings->rcr_rings[rdc]; 3922678453a8Sspeer if (ring == 0) { 3923678453a8Sspeer /* 3924678453a8Sspeer * This is a big deal only if we are 3925678453a8Sspeer * *not* in an LDOMs environment. 3926678453a8Sspeer */ 3927678453a8Sspeer if (nxgep->environs == SOLARIS_DOMAIN) { 3928678453a8Sspeer cmn_err(CE_NOTE, 3929678453a8Sspeer "==> nxge_m_resources: " 3930678453a8Sspeer "ring %d == 0", rdc); 3931678453a8Sspeer } 3932678453a8Sspeer continue; 3933678453a8Sspeer } 3934678453a8Sspeer ring->rcr_mac_handle = mac_resource_add 3935678453a8Sspeer (nxgep->mach, (mac_resource_t *)&mrf); 393644961713Sgirish 3937678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 3938678453a8Sspeer "==> nxge_m_resources: RDC %d RCR %p MAC handle %p", 3939678453a8Sspeer rdc, ring, ring->rcr_mac_handle)); 3940678453a8Sspeer } 394144961713Sgirish } 394244961713Sgirish 394314ea4bb7Ssd nxge_m_resources_exit: 394444961713Sgirish MUTEX_EXIT(nxgep->genlock); 394544961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources")); 394644961713Sgirish } 394744961713Sgirish 3948678453a8Sspeer void 394958324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory) 395058324dfcSspeer { 395158324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 395258324dfcSspeer int i; 395358324dfcSspeer nxge_mmac_t *mmac_info; 395458324dfcSspeer 395558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 395658324dfcSspeer 395758324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 395858324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 395958324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 396058324dfcSspeer 396158324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 396258324dfcSspeer if (factory) { 396358324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 39644045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 39654045d941Ssowmini (ETHERADDRL-1) - i]; 396658324dfcSspeer } else { 396758324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 39684045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 39694045d941Ssowmini (ETHERADDRL - 1) - i]; 397058324dfcSspeer } 397158324dfcSspeer } 397258324dfcSspeer } 397358324dfcSspeer 397458324dfcSspeer /* 397558324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 397658324dfcSspeer */ 397758324dfcSspeer static int 397858324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot) 397958324dfcSspeer { 398058324dfcSspeer uint8_t addrn; 398158324dfcSspeer uint8_t portn; 398258324dfcSspeer npi_mac_addr_t altmac; 39837b9fa28bSspeer hostinfo_t mac_rdc; 39847b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 398558324dfcSspeer 398658324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 398758324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 398858324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 398958324dfcSspeer 399058324dfcSspeer portn = nxgep->mac.portnum; 399158324dfcSspeer addrn = (uint8_t)slot - 1; 399258324dfcSspeer 399358324dfcSspeer if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn, 39944045d941Ssowmini addrn, &altmac) != NPI_SUCCESS) 399558324dfcSspeer return (EIO); 39967b9fa28bSspeer 39977b9fa28bSspeer /* 39987b9fa28bSspeer * Set the rdc table number for the host info entry 39997b9fa28bSspeer * for this mac address slot. 40007b9fa28bSspeer */ 40017b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 40027b9fa28bSspeer mac_rdc.value = 0; 40037b9fa28bSspeer mac_rdc.bits.w0.rdc_tbl_num = clscfgp->mac_host_info[addrn].rdctbl; 40047b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 40057b9fa28bSspeer 40067b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 40077b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 40087b9fa28bSspeer return (EIO); 40097b9fa28bSspeer } 40107b9fa28bSspeer 401158324dfcSspeer /* 401258324dfcSspeer * Enable comparison with the alternate MAC address. 401358324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 401458324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 401558324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 401658324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 401758324dfcSspeer */ 401858324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 401958324dfcSspeer addrn = (uint8_t)slot - 1; 402058324dfcSspeer else 402158324dfcSspeer addrn = (uint8_t)slot; 402258324dfcSspeer 402358324dfcSspeer if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn) 40244045d941Ssowmini != NPI_SUCCESS) 402558324dfcSspeer return (EIO); 402658324dfcSspeer 402758324dfcSspeer return (0); 402858324dfcSspeer } 402958324dfcSspeer 403058324dfcSspeer /* 403158324dfcSspeer * nxeg_m_mmac_add() - find an unused address slot, set the address 403258324dfcSspeer * value to the one specified, enable the port to start filtering on 403358324dfcSspeer * the new MAC address. Returns 0 on success. 403458324dfcSspeer */ 4035678453a8Sspeer int 403658324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 403758324dfcSspeer { 403858324dfcSspeer p_nxge_t nxgep = arg; 403958324dfcSspeer mac_addr_slot_t slot; 404058324dfcSspeer nxge_mmac_t *mmac_info; 404158324dfcSspeer int err; 404258324dfcSspeer nxge_status_t status; 404358324dfcSspeer 404458324dfcSspeer mutex_enter(nxgep->genlock); 404558324dfcSspeer 404658324dfcSspeer /* 404758324dfcSspeer * Make sure that nxge is initialized, if _start() has 404858324dfcSspeer * not been called. 404958324dfcSspeer */ 405058324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 405158324dfcSspeer status = nxge_init(nxgep); 405258324dfcSspeer if (status != NXGE_OK) { 405358324dfcSspeer mutex_exit(nxgep->genlock); 405458324dfcSspeer return (ENXIO); 405558324dfcSspeer } 405658324dfcSspeer } 405758324dfcSspeer 405858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 405958324dfcSspeer if (mmac_info->naddrfree == 0) { 406058324dfcSspeer mutex_exit(nxgep->genlock); 406158324dfcSspeer return (ENOSPC); 406258324dfcSspeer } 406358324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 40644045d941Ssowmini maddr->mma_addrlen)) { 406558324dfcSspeer mutex_exit(nxgep->genlock); 406658324dfcSspeer return (EINVAL); 406758324dfcSspeer } 406858324dfcSspeer /* 406958324dfcSspeer * Search for the first available slot. Because naddrfree 407058324dfcSspeer * is not zero, we are guaranteed to find one. 407158324dfcSspeer * Slot 0 is for unique (primary) MAC. The first alternate 407258324dfcSspeer * MAC slot is slot 1. 407358324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4074678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 407558324dfcSspeer * MAC addresses. We first search among the slots without bundled 407658324dfcSspeer * factory MACs. If we fail to find one in that range, then we 407758324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 407858324dfcSspeer * will be wasted while the slot is used with a user MAC address. 407958324dfcSspeer * But the slot could be used by factory MAC again after calling 408058324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 408158324dfcSspeer */ 408258324dfcSspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 408358324dfcSspeer for (slot = mmac_info->num_factory_mmac + 1; 40844045d941Ssowmini slot <= mmac_info->num_mmac; slot++) { 408558324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 408658324dfcSspeer break; 408758324dfcSspeer } 408858324dfcSspeer if (slot > mmac_info->num_mmac) { 408958324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 40904045d941Ssowmini slot++) { 409158324dfcSspeer if (!(mmac_info->mac_pool[slot].flags 40924045d941Ssowmini & MMAC_SLOT_USED)) 409358324dfcSspeer break; 409458324dfcSspeer } 409558324dfcSspeer } 409658324dfcSspeer } else { 409758324dfcSspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 409858324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 409958324dfcSspeer break; 410058324dfcSspeer } 410158324dfcSspeer } 410258324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 410358324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) { 410458324dfcSspeer mutex_exit(nxgep->genlock); 410558324dfcSspeer return (err); 410658324dfcSspeer } 410758324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 410858324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 410958324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 411058324dfcSspeer mmac_info->naddrfree--; 411158324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 411258324dfcSspeer 411358324dfcSspeer maddr->mma_slot = slot; 411458324dfcSspeer 411558324dfcSspeer mutex_exit(nxgep->genlock); 411658324dfcSspeer return (0); 411758324dfcSspeer } 411858324dfcSspeer 411958324dfcSspeer /* 412058324dfcSspeer * This function reserves an unused slot and programs the slot and the HW 412158324dfcSspeer * with a factory mac address. 412258324dfcSspeer */ 412358324dfcSspeer static int 412458324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr) 412558324dfcSspeer { 412658324dfcSspeer p_nxge_t nxgep = arg; 412758324dfcSspeer mac_addr_slot_t slot; 412858324dfcSspeer nxge_mmac_t *mmac_info; 412958324dfcSspeer int err; 413058324dfcSspeer nxge_status_t status; 413158324dfcSspeer 413258324dfcSspeer mutex_enter(nxgep->genlock); 413358324dfcSspeer 413458324dfcSspeer /* 413558324dfcSspeer * Make sure that nxge is initialized, if _start() has 413658324dfcSspeer * not been called. 413758324dfcSspeer */ 413858324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 413958324dfcSspeer status = nxge_init(nxgep); 414058324dfcSspeer if (status != NXGE_OK) { 414158324dfcSspeer mutex_exit(nxgep->genlock); 414258324dfcSspeer return (ENXIO); 414358324dfcSspeer } 414458324dfcSspeer } 414558324dfcSspeer 414658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 414758324dfcSspeer if (mmac_info->naddrfree == 0) { 414858324dfcSspeer mutex_exit(nxgep->genlock); 414958324dfcSspeer return (ENOSPC); 415058324dfcSspeer } 415158324dfcSspeer 415258324dfcSspeer slot = maddr->mma_slot; 415358324dfcSspeer if (slot == -1) { /* -1: Take the first available slot */ 415458324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) { 415558324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 415658324dfcSspeer break; 415758324dfcSspeer } 415858324dfcSspeer if (slot > mmac_info->num_factory_mmac) { 415958324dfcSspeer mutex_exit(nxgep->genlock); 416058324dfcSspeer return (ENOSPC); 416158324dfcSspeer } 416258324dfcSspeer } 416358324dfcSspeer if (slot < 1 || slot > mmac_info->num_factory_mmac) { 416458324dfcSspeer /* 416558324dfcSspeer * Do not support factory MAC at a slot greater than 416658324dfcSspeer * num_factory_mmac even when there are available factory 416758324dfcSspeer * MAC addresses because the alternate MACs are bundled with 416858324dfcSspeer * slot[1] through slot[num_factory_mmac] 416958324dfcSspeer */ 417058324dfcSspeer mutex_exit(nxgep->genlock); 417158324dfcSspeer return (EINVAL); 417258324dfcSspeer } 417358324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 417458324dfcSspeer mutex_exit(nxgep->genlock); 417558324dfcSspeer return (EBUSY); 417658324dfcSspeer } 417758324dfcSspeer /* Verify the address to be reserved */ 417858324dfcSspeer if (!mac_unicst_verify(nxgep->mach, 41794045d941Ssowmini mmac_info->factory_mac_pool[slot], ETHERADDRL)) { 418058324dfcSspeer mutex_exit(nxgep->genlock); 418158324dfcSspeer return (EINVAL); 418258324dfcSspeer } 418358324dfcSspeer if (err = nxge_altmac_set(nxgep, 41844045d941Ssowmini mmac_info->factory_mac_pool[slot], slot)) { 418558324dfcSspeer mutex_exit(nxgep->genlock); 418658324dfcSspeer return (err); 418758324dfcSspeer } 418858324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL); 418958324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 419058324dfcSspeer mmac_info->naddrfree--; 419158324dfcSspeer 419258324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_TRUE); 419358324dfcSspeer mutex_exit(nxgep->genlock); 419458324dfcSspeer 419558324dfcSspeer /* Pass info back to the caller */ 419658324dfcSspeer maddr->mma_slot = slot; 419758324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 419858324dfcSspeer maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 419958324dfcSspeer 420058324dfcSspeer return (0); 420158324dfcSspeer } 420258324dfcSspeer 420358324dfcSspeer /* 420458324dfcSspeer * Remove the specified mac address and update the HW not to filter 420558324dfcSspeer * the mac address anymore. 420658324dfcSspeer */ 4207678453a8Sspeer int 420858324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 420958324dfcSspeer { 421058324dfcSspeer p_nxge_t nxgep = arg; 421158324dfcSspeer nxge_mmac_t *mmac_info; 421258324dfcSspeer uint8_t addrn; 421358324dfcSspeer uint8_t portn; 421458324dfcSspeer int err = 0; 421558324dfcSspeer nxge_status_t status; 421658324dfcSspeer 421758324dfcSspeer mutex_enter(nxgep->genlock); 421858324dfcSspeer 421958324dfcSspeer /* 422058324dfcSspeer * Make sure that nxge is initialized, if _start() has 422158324dfcSspeer * not been called. 422258324dfcSspeer */ 422358324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 422458324dfcSspeer status = nxge_init(nxgep); 422558324dfcSspeer if (status != NXGE_OK) { 422658324dfcSspeer mutex_exit(nxgep->genlock); 422758324dfcSspeer return (ENXIO); 422858324dfcSspeer } 422958324dfcSspeer } 423058324dfcSspeer 423158324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 423258324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 423358324dfcSspeer mutex_exit(nxgep->genlock); 423458324dfcSspeer return (EINVAL); 423558324dfcSspeer } 423658324dfcSspeer 423758324dfcSspeer portn = nxgep->mac.portnum; 423858324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 423958324dfcSspeer addrn = (uint8_t)slot - 1; 424058324dfcSspeer else 424158324dfcSspeer addrn = (uint8_t)slot; 424258324dfcSspeer 424358324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 424458324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 42454045d941Ssowmini == NPI_SUCCESS) { 424658324dfcSspeer mmac_info->naddrfree++; 424758324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 424858324dfcSspeer /* 424958324dfcSspeer * Regardless if the MAC we just stopped filtering 425058324dfcSspeer * is a user addr or a facory addr, we must set 425158324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 425258324dfcSspeer * associated factory MAC to indicate that a factory 425358324dfcSspeer * MAC is available. 425458324dfcSspeer */ 425558324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 425658324dfcSspeer mmac_info->mac_pool[slot].flags 42574045d941Ssowmini |= MMAC_VENDOR_ADDR; 425858324dfcSspeer } 425958324dfcSspeer /* 426058324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 426158324dfcSspeer * alternate MAC address if the slot is not used. 426258324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 426358324dfcSspeer * when the slot is not used!) 426458324dfcSspeer */ 426558324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 426658324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 426758324dfcSspeer } else { 426858324dfcSspeer err = EIO; 426958324dfcSspeer } 427058324dfcSspeer } else { 427158324dfcSspeer err = EINVAL; 427258324dfcSspeer } 427358324dfcSspeer 427458324dfcSspeer mutex_exit(nxgep->genlock); 427558324dfcSspeer return (err); 427658324dfcSspeer } 427758324dfcSspeer 427858324dfcSspeer /* 427958324dfcSspeer * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve(). 428058324dfcSspeer */ 428158324dfcSspeer static int 428258324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 428358324dfcSspeer { 428458324dfcSspeer p_nxge_t nxgep = arg; 428558324dfcSspeer mac_addr_slot_t slot; 428658324dfcSspeer nxge_mmac_t *mmac_info; 428758324dfcSspeer int err = 0; 428858324dfcSspeer nxge_status_t status; 428958324dfcSspeer 429058324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 42914045d941Ssowmini maddr->mma_addrlen)) 429258324dfcSspeer return (EINVAL); 429358324dfcSspeer 429458324dfcSspeer slot = maddr->mma_slot; 429558324dfcSspeer 429658324dfcSspeer mutex_enter(nxgep->genlock); 429758324dfcSspeer 429858324dfcSspeer /* 429958324dfcSspeer * Make sure that nxge is initialized, if _start() has 430058324dfcSspeer * not been called. 430158324dfcSspeer */ 430258324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 430358324dfcSspeer status = nxge_init(nxgep); 430458324dfcSspeer if (status != NXGE_OK) { 430558324dfcSspeer mutex_exit(nxgep->genlock); 430658324dfcSspeer return (ENXIO); 430758324dfcSspeer } 430858324dfcSspeer } 430958324dfcSspeer 431058324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 431158324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 431258324dfcSspeer mutex_exit(nxgep->genlock); 431358324dfcSspeer return (EINVAL); 431458324dfcSspeer } 431558324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 431658324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) 43174045d941Ssowmini != 0) { 431858324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 43194045d941Ssowmini ETHERADDRL); 432058324dfcSspeer /* 432158324dfcSspeer * Assume that the MAC passed down from the caller 432258324dfcSspeer * is not a factory MAC address (The user should 432358324dfcSspeer * call mmac_remove followed by mmac_reserve if 432458324dfcSspeer * he wants to use the factory MAC for this slot). 432558324dfcSspeer */ 432658324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 432758324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 432858324dfcSspeer } 432958324dfcSspeer } else { 433058324dfcSspeer err = EINVAL; 433158324dfcSspeer } 433258324dfcSspeer mutex_exit(nxgep->genlock); 433358324dfcSspeer return (err); 433458324dfcSspeer } 433558324dfcSspeer 433658324dfcSspeer /* 433758324dfcSspeer * nxge_m_mmac_get() - Get the MAC address and other information 433858324dfcSspeer * related to the slot. mma_flags should be set to 0 in the call. 433958324dfcSspeer * Note: although kstat shows MAC address as zero when a slot is 434058324dfcSspeer * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC 434158324dfcSspeer * to the caller as long as the slot is not using a user MAC address. 434258324dfcSspeer * The following table shows the rules, 434358324dfcSspeer * 434458324dfcSspeer * USED VENDOR mma_addr 434558324dfcSspeer * ------------------------------------------------------------ 434658324dfcSspeer * (1) Slot uses a user MAC: yes no user MAC 434758324dfcSspeer * (2) Slot uses a factory MAC: yes yes factory MAC 434858324dfcSspeer * (3) Slot is not used but is 434958324dfcSspeer * factory MAC capable: no yes factory MAC 435058324dfcSspeer * (4) Slot is not used and is 435158324dfcSspeer * not factory MAC capable: no no 0 435258324dfcSspeer * ------------------------------------------------------------ 435358324dfcSspeer */ 435458324dfcSspeer static int 435558324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 435658324dfcSspeer { 435758324dfcSspeer nxge_t *nxgep = arg; 435858324dfcSspeer mac_addr_slot_t slot; 435958324dfcSspeer nxge_mmac_t *mmac_info; 436058324dfcSspeer nxge_status_t status; 436158324dfcSspeer 436258324dfcSspeer slot = maddr->mma_slot; 436358324dfcSspeer 436458324dfcSspeer mutex_enter(nxgep->genlock); 436558324dfcSspeer 436658324dfcSspeer /* 436758324dfcSspeer * Make sure that nxge is initialized, if _start() has 436858324dfcSspeer * not been called. 436958324dfcSspeer */ 437058324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 437158324dfcSspeer status = nxge_init(nxgep); 437258324dfcSspeer if (status != NXGE_OK) { 437358324dfcSspeer mutex_exit(nxgep->genlock); 437458324dfcSspeer return (ENXIO); 437558324dfcSspeer } 437658324dfcSspeer } 437758324dfcSspeer 437858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 437958324dfcSspeer 438058324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 438158324dfcSspeer mutex_exit(nxgep->genlock); 438258324dfcSspeer return (EINVAL); 438358324dfcSspeer } 438458324dfcSspeer maddr->mma_flags = 0; 438558324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) 438658324dfcSspeer maddr->mma_flags |= MMAC_SLOT_USED; 438758324dfcSspeer 438858324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) { 438958324dfcSspeer maddr->mma_flags |= MMAC_VENDOR_ADDR; 439058324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], 43914045d941Ssowmini maddr->mma_addr, ETHERADDRL); 439258324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 439358324dfcSspeer } else { 439458324dfcSspeer if (maddr->mma_flags & MMAC_SLOT_USED) { 439558324dfcSspeer bcopy(mmac_info->mac_pool[slot].addr, 43964045d941Ssowmini maddr->mma_addr, ETHERADDRL); 439758324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 439858324dfcSspeer } else { 439958324dfcSspeer bzero(maddr->mma_addr, ETHERADDRL); 440058324dfcSspeer maddr->mma_addrlen = 0; 440158324dfcSspeer } 440258324dfcSspeer } 440358324dfcSspeer mutex_exit(nxgep->genlock); 440458324dfcSspeer return (0); 440558324dfcSspeer } 440658324dfcSspeer 440744961713Sgirish static boolean_t 440844961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 440944961713Sgirish { 441058324dfcSspeer nxge_t *nxgep = arg; 441158324dfcSspeer uint32_t *txflags = cap_data; 441258324dfcSspeer multiaddress_capab_t *mmacp = cap_data; 441344961713Sgirish 441458324dfcSspeer switch (cap) { 441558324dfcSspeer case MAC_CAPAB_HCKSUM: 4416678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4417b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4418b4d05839Sml if (nxge_cksum_offload <= 1) { 4419678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4420678453a8Sspeer } 442144961713Sgirish break; 4422678453a8Sspeer 442344961713Sgirish case MAC_CAPAB_POLL: 442444961713Sgirish /* 442544961713Sgirish * There's nothing for us to fill in, simply returning 442644961713Sgirish * B_TRUE stating that we support polling is sufficient. 442744961713Sgirish */ 442844961713Sgirish break; 442944961713Sgirish 443058324dfcSspeer case MAC_CAPAB_MULTIADDRESS: 4431678453a8Sspeer mmacp = (multiaddress_capab_t *)cap_data; 443258324dfcSspeer mutex_enter(nxgep->genlock); 443358324dfcSspeer 443458324dfcSspeer mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac; 443558324dfcSspeer mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree; 4436b4d05839Sml mmacp->maddr_flag = 0; /* 0 is required by PSARC2006/265 */ 443758324dfcSspeer /* 443858324dfcSspeer * maddr_handle is driver's private data, passed back to 443958324dfcSspeer * entry point functions as arg. 444058324dfcSspeer */ 444158324dfcSspeer mmacp->maddr_handle = nxgep; 444258324dfcSspeer mmacp->maddr_add = nxge_m_mmac_add; 444358324dfcSspeer mmacp->maddr_remove = nxge_m_mmac_remove; 444458324dfcSspeer mmacp->maddr_modify = nxge_m_mmac_modify; 444558324dfcSspeer mmacp->maddr_get = nxge_m_mmac_get; 444658324dfcSspeer mmacp->maddr_reserve = nxge_m_mmac_reserve; 444758324dfcSspeer 444858324dfcSspeer mutex_exit(nxgep->genlock); 444958324dfcSspeer break; 4450678453a8Sspeer 445130ac2e7bSml case MAC_CAPAB_LSO: { 445230ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 445330ac2e7bSml 44543d16f8e7Sml if (nxgep->soft_lso_enable) { 4455b4d05839Sml if (nxge_cksum_offload <= 1) { 4456b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4457b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4458b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4459b4d05839Sml } 4460b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4461b4d05839Sml nxge_lso_max; 446230ac2e7bSml } 446330ac2e7bSml break; 446430ac2e7bSml } else { 446530ac2e7bSml return (B_FALSE); 446630ac2e7bSml } 446730ac2e7bSml } 446830ac2e7bSml 4469678453a8Sspeer #if defined(sun4v) 4470678453a8Sspeer case MAC_CAPAB_RINGS: { 4471678453a8Sspeer mac_capab_rings_t *mrings = (mac_capab_rings_t *)cap_data; 4472678453a8Sspeer 4473678453a8Sspeer /* 4474678453a8Sspeer * Only the service domain driver responds to 4475678453a8Sspeer * this capability request. 4476678453a8Sspeer */ 4477678453a8Sspeer if (isLDOMservice(nxgep)) { 4478678453a8Sspeer mrings->mr_handle = (void *)nxgep; 4479678453a8Sspeer 4480678453a8Sspeer /* 4481678453a8Sspeer * No dynamic allocation of groups and 4482678453a8Sspeer * rings at this time. Shares dictate the 4483*6f157acbSml * configuration. 4484678453a8Sspeer */ 4485678453a8Sspeer mrings->mr_gadd_ring = NULL; 4486678453a8Sspeer mrings->mr_grem_ring = NULL; 4487678453a8Sspeer mrings->mr_rget = NULL; 4488678453a8Sspeer mrings->mr_gget = nxge_hio_group_get; 4489678453a8Sspeer 4490678453a8Sspeer if (mrings->mr_type == MAC_RING_TYPE_RX) { 4491678453a8Sspeer mrings->mr_rnum = 8; /* XXX */ 4492678453a8Sspeer mrings->mr_gnum = 6; /* XXX */ 4493678453a8Sspeer } else { 4494678453a8Sspeer mrings->mr_rnum = 8; /* XXX */ 4495678453a8Sspeer mrings->mr_gnum = 0; /* XXX */ 4496678453a8Sspeer } 4497678453a8Sspeer } else 4498678453a8Sspeer return (B_FALSE); 4499678453a8Sspeer break; 4500678453a8Sspeer } 4501678453a8Sspeer 4502678453a8Sspeer case MAC_CAPAB_SHARES: { 4503678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4504678453a8Sspeer 4505678453a8Sspeer /* 4506678453a8Sspeer * Only the service domain driver responds to 4507678453a8Sspeer * this capability request. 4508678453a8Sspeer */ 4509678453a8Sspeer if (isLDOMservice(nxgep)) { 4510678453a8Sspeer mshares->ms_snum = 3; 4511678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4512678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4513678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4514678453a8Sspeer mshares->ms_sadd = NULL; 4515678453a8Sspeer mshares->ms_sremove = NULL; 4516678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4517678453a8Sspeer } else 4518678453a8Sspeer return (B_FALSE); 4519678453a8Sspeer break; 4520678453a8Sspeer } 4521678453a8Sspeer #endif 452244961713Sgirish default: 452344961713Sgirish return (B_FALSE); 452444961713Sgirish } 452544961713Sgirish return (B_TRUE); 452644961713Sgirish } 452744961713Sgirish 45281bd6825cSml static boolean_t 45291bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 45301bd6825cSml { 45311bd6825cSml /* 45321bd6825cSml * All adv_* parameters are locked (read-only) while 45331bd6825cSml * the device is in any sort of loopback mode ... 45341bd6825cSml */ 45351bd6825cSml switch (pr_num) { 45361bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 45371bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 45381bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 45391bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 45401bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 45411bd6825cSml case DLD_PROP_EN_100FDX_CAP: 45421bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 45431bd6825cSml case DLD_PROP_EN_100HDX_CAP: 45441bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 45451bd6825cSml case DLD_PROP_EN_10FDX_CAP: 45461bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 45471bd6825cSml case DLD_PROP_EN_10HDX_CAP: 45481bd6825cSml case DLD_PROP_AUTONEG: 45491bd6825cSml case DLD_PROP_FLOWCTRL: 45501bd6825cSml return (B_TRUE); 45511bd6825cSml } 45521bd6825cSml return (B_FALSE); 45531bd6825cSml } 45541bd6825cSml 45551bd6825cSml /* 45561bd6825cSml * callback functions for set/get of properties 45571bd6825cSml */ 45581bd6825cSml static int 45591bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 45601bd6825cSml uint_t pr_valsize, const void *pr_val) 45611bd6825cSml { 45621bd6825cSml nxge_t *nxgep = barg; 45631bd6825cSml p_nxge_param_t param_arr; 45641bd6825cSml p_nxge_stats_t statsp; 45651bd6825cSml int err = 0; 45661bd6825cSml uint8_t val; 45671bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 45681bd6825cSml link_flowctrl_t fl; 45691bd6825cSml 45701bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 45711bd6825cSml param_arr = nxgep->param_arr; 45721bd6825cSml statsp = nxgep->statsp; 45731bd6825cSml mutex_enter(nxgep->genlock); 45741bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 45751bd6825cSml nxge_param_locked(pr_num)) { 45761bd6825cSml /* 45771bd6825cSml * All adv_* parameters are locked (read-only) 45781bd6825cSml * while the device is in any sort of loopback mode. 45791bd6825cSml */ 45801bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45811bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 45821bd6825cSml mutex_exit(nxgep->genlock); 45831bd6825cSml return (EBUSY); 45841bd6825cSml } 45851bd6825cSml 45861bd6825cSml val = *(uint8_t *)pr_val; 45871bd6825cSml switch (pr_num) { 45881bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 45891bd6825cSml nxgep->param_en_1000fdx = val; 45901bd6825cSml param_arr[param_anar_1000fdx].value = val; 45911bd6825cSml 45921bd6825cSml goto reprogram; 45931bd6825cSml 45941bd6825cSml case DLD_PROP_EN_100FDX_CAP: 45951bd6825cSml nxgep->param_en_100fdx = val; 45961bd6825cSml param_arr[param_anar_100fdx].value = val; 45971bd6825cSml 45981bd6825cSml goto reprogram; 45991bd6825cSml 46001bd6825cSml case DLD_PROP_EN_10FDX_CAP: 46011bd6825cSml nxgep->param_en_10fdx = val; 46021bd6825cSml param_arr[param_anar_10fdx].value = val; 46031bd6825cSml 46041bd6825cSml goto reprogram; 46051bd6825cSml 46061bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 46071bd6825cSml case DLD_PROP_EN_100HDX_CAP: 46081bd6825cSml case DLD_PROP_EN_10HDX_CAP: 46091bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 46101bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 46111bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 46121bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 46131bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 46141bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 46151bd6825cSml case DLD_PROP_STATUS: 46161bd6825cSml case DLD_PROP_SPEED: 46171bd6825cSml case DLD_PROP_DUPLEX: 46181bd6825cSml err = EINVAL; /* cannot set read-only properties */ 46191bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46201bd6825cSml "==> nxge_m_setprop: read only property %d", 46211bd6825cSml pr_num)); 46221bd6825cSml break; 46231bd6825cSml 46241bd6825cSml case DLD_PROP_AUTONEG: 46251bd6825cSml param_arr[param_autoneg].value = val; 46261bd6825cSml 46271bd6825cSml goto reprogram; 46281bd6825cSml 46294045d941Ssowmini case DLD_PROP_MTU: 46301bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 46311bd6825cSml err = EBUSY; 46321bd6825cSml break; 46331bd6825cSml } 46341bd6825cSml 46351bd6825cSml cur_mtu = nxgep->mac.default_mtu; 46361bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 46371bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46381bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 46391bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 46401bd6825cSml 46411bd6825cSml if (new_mtu == cur_mtu) { 46421bd6825cSml err = 0; 46431bd6825cSml break; 46441bd6825cSml } 46451bd6825cSml if (new_mtu < NXGE_DEFAULT_MTU || 46461bd6825cSml new_mtu > NXGE_MAXIMUM_MTU) { 46471bd6825cSml err = EINVAL; 46481bd6825cSml break; 46491bd6825cSml } 46501bd6825cSml 46511bd6825cSml if ((new_mtu > NXGE_DEFAULT_MTU) && 46521bd6825cSml !nxgep->mac.is_jumbo) { 46531bd6825cSml err = EINVAL; 46541bd6825cSml break; 46551bd6825cSml } 46561bd6825cSml 46571bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 46581bd6825cSml nxgep->mac.maxframesize = (uint16_t) 46591bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 46601bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 4661c2d37b8bSml nxgep->mac.maxframesize = 4662c2d37b8bSml (uint16_t)old_framesize; 46631bd6825cSml err = EINVAL; 46641bd6825cSml break; 46651bd6825cSml } 46661bd6825cSml 46671bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 46681bd6825cSml if (err) { 4669c2d37b8bSml nxgep->mac.maxframesize = 4670c2d37b8bSml (uint16_t)old_framesize; 46711bd6825cSml err = EINVAL; 46721bd6825cSml break; 46731bd6825cSml } 46741bd6825cSml 46751bd6825cSml nxgep->mac.default_mtu = new_mtu; 46761bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46771bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 46781bd6825cSml new_mtu, nxgep->mac.maxframesize)); 46791bd6825cSml break; 46801bd6825cSml 46811bd6825cSml case DLD_PROP_FLOWCTRL: 46821bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 46831bd6825cSml switch (fl) { 46841bd6825cSml default: 46851bd6825cSml err = EINVAL; 46861bd6825cSml break; 46871bd6825cSml 46881bd6825cSml case LINK_FLOWCTRL_NONE: 46891bd6825cSml param_arr[param_anar_pause].value = 0; 46901bd6825cSml break; 46911bd6825cSml 46921bd6825cSml case LINK_FLOWCTRL_RX: 46931bd6825cSml param_arr[param_anar_pause].value = 1; 46941bd6825cSml break; 46951bd6825cSml 46961bd6825cSml case LINK_FLOWCTRL_TX: 46971bd6825cSml case LINK_FLOWCTRL_BI: 46981bd6825cSml err = EINVAL; 46991bd6825cSml break; 47001bd6825cSml } 47011bd6825cSml 47021bd6825cSml reprogram: 47031bd6825cSml if (err == 0) { 47041bd6825cSml if (!nxge_param_link_update(nxgep)) { 47051bd6825cSml err = EINVAL; 47061bd6825cSml } 47071bd6825cSml } 47081bd6825cSml break; 47094045d941Ssowmini case DLD_PROP_PRIVATE: 47101bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47111bd6825cSml "==> nxge_m_setprop: private property")); 47121bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 47131bd6825cSml pr_val); 47141bd6825cSml break; 47154045d941Ssowmini 47164045d941Ssowmini default: 47174045d941Ssowmini err = ENOTSUP; 47184045d941Ssowmini break; 47191bd6825cSml } 47201bd6825cSml 47211bd6825cSml mutex_exit(nxgep->genlock); 47221bd6825cSml 47231bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47241bd6825cSml "<== nxge_m_setprop (return %d)", err)); 47251bd6825cSml return (err); 47261bd6825cSml } 47271bd6825cSml 47281bd6825cSml static int 47291bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 47304045d941Ssowmini uint_t pr_flags, uint_t pr_valsize, void *pr_val) 47311bd6825cSml { 47321bd6825cSml nxge_t *nxgep = barg; 47331bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 47341bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 47351bd6825cSml int err = 0; 47361bd6825cSml link_flowctrl_t fl; 47371bd6825cSml uint64_t tmp = 0; 47384045d941Ssowmini link_state_t ls; 47394045d941Ssowmini boolean_t is_default = (pr_flags & DLD_DEFAULT); 47401bd6825cSml 47411bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47421bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 47434045d941Ssowmini 47444045d941Ssowmini if (pr_valsize == 0) 47454045d941Ssowmini return (EINVAL); 47464045d941Ssowmini 47474045d941Ssowmini if ((is_default) && (pr_num != DLD_PROP_PRIVATE)) { 47484045d941Ssowmini err = nxge_get_def_val(nxgep, pr_num, pr_valsize, pr_val); 47494045d941Ssowmini return (err); 47504045d941Ssowmini } 47514045d941Ssowmini 47521bd6825cSml bzero(pr_val, pr_valsize); 47531bd6825cSml switch (pr_num) { 47541bd6825cSml case DLD_PROP_DUPLEX: 47551bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 47561bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47571bd6825cSml "==> nxge_m_getprop: duplex mode %d", 47581bd6825cSml *(uint8_t *)pr_val)); 47591bd6825cSml break; 47601bd6825cSml 47611bd6825cSml case DLD_PROP_SPEED: 47621bd6825cSml if (pr_valsize < sizeof (uint64_t)) 47631bd6825cSml return (EINVAL); 47641bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 47651bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 47661bd6825cSml break; 47671bd6825cSml 47681bd6825cSml case DLD_PROP_STATUS: 47694045d941Ssowmini if (pr_valsize < sizeof (link_state_t)) 47701bd6825cSml return (EINVAL); 47714045d941Ssowmini if (!statsp->mac_stats.link_up) 47724045d941Ssowmini ls = LINK_STATE_DOWN; 47734045d941Ssowmini else 47744045d941Ssowmini ls = LINK_STATE_UP; 47754045d941Ssowmini bcopy(&ls, pr_val, sizeof (ls)); 47761bd6825cSml break; 47771bd6825cSml 47781bd6825cSml case DLD_PROP_AUTONEG: 47791bd6825cSml *(uint8_t *)pr_val = 47801bd6825cSml param_arr[param_autoneg].value; 47811bd6825cSml break; 47821bd6825cSml 47831bd6825cSml case DLD_PROP_FLOWCTRL: 47841bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 47851bd6825cSml return (EINVAL); 47861bd6825cSml 47871bd6825cSml fl = LINK_FLOWCTRL_NONE; 47881bd6825cSml if (param_arr[param_anar_pause].value) { 47891bd6825cSml fl = LINK_FLOWCTRL_RX; 47901bd6825cSml } 47911bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 47921bd6825cSml break; 47931bd6825cSml 47941bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 47951bd6825cSml *(uint8_t *)pr_val = 47961bd6825cSml param_arr[param_anar_1000fdx].value; 47971bd6825cSml break; 47981bd6825cSml 47991bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 48001bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 48011bd6825cSml break; 48021bd6825cSml 48031bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 48041bd6825cSml *(uint8_t *)pr_val = 48051bd6825cSml param_arr[param_anar_100fdx].value; 48061bd6825cSml break; 48071bd6825cSml 48081bd6825cSml case DLD_PROP_EN_100FDX_CAP: 48091bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 48101bd6825cSml break; 48111bd6825cSml 48121bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 48131bd6825cSml *(uint8_t *)pr_val = 48141bd6825cSml param_arr[param_anar_10fdx].value; 48151bd6825cSml break; 48161bd6825cSml 48171bd6825cSml case DLD_PROP_EN_10FDX_CAP: 48181bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 48191bd6825cSml break; 48201bd6825cSml 48211bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 48221bd6825cSml case DLD_PROP_EN_100HDX_CAP: 48231bd6825cSml case DLD_PROP_EN_10HDX_CAP: 48241bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 48251bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 48261bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 48274045d941Ssowmini err = ENOTSUP; 48281bd6825cSml break; 48291bd6825cSml 48304045d941Ssowmini case DLD_PROP_PRIVATE: 48314045d941Ssowmini err = nxge_get_priv_prop(nxgep, pr_name, pr_flags, 48324045d941Ssowmini pr_valsize, pr_val); 48334045d941Ssowmini break; 48341bd6825cSml default: 48354045d941Ssowmini err = EINVAL; 48364045d941Ssowmini break; 48371bd6825cSml } 48381bd6825cSml 48391bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 48401bd6825cSml 48411bd6825cSml return (err); 48421bd6825cSml } 48431bd6825cSml 48441bd6825cSml /* ARGSUSED */ 48451bd6825cSml static int 48461bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 48471bd6825cSml const void *pr_val) 48481bd6825cSml { 48491bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 48501bd6825cSml int err = 0; 48511bd6825cSml long result; 48521bd6825cSml 48531bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48541bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 48551bd6825cSml 48561bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 48571bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48581bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48591bd6825cSml "<== nxge_set_priv_prop: name %s " 48601bd6825cSml "pr_val %s result %d " 48611bd6825cSml "param %d is_jumbo %d", 48621bd6825cSml pr_name, pr_val, result, 48631bd6825cSml param_arr[param_accept_jumbo].value, 48641bd6825cSml nxgep->mac.is_jumbo)); 48651bd6825cSml 48661bd6825cSml if (result > 1 || result < 0) { 48671bd6825cSml err = EINVAL; 48681bd6825cSml } else { 48691bd6825cSml if (nxgep->mac.is_jumbo == 48701bd6825cSml (uint32_t)result) { 48711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48721bd6825cSml "no change (%d %d)", 48731bd6825cSml nxgep->mac.is_jumbo, 48741bd6825cSml result)); 48751bd6825cSml return (0); 48761bd6825cSml } 48771bd6825cSml } 48781bd6825cSml 48791bd6825cSml param_arr[param_accept_jumbo].value = result; 48801bd6825cSml nxgep->mac.is_jumbo = B_FALSE; 48811bd6825cSml if (result) { 48821bd6825cSml nxgep->mac.is_jumbo = B_TRUE; 48831bd6825cSml } 48841bd6825cSml 48851bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48861bd6825cSml "<== nxge_set_priv_prop: name %s (value %d) is_jumbo %d", 48871bd6825cSml pr_name, result, nxgep->mac.is_jumbo)); 48881bd6825cSml 48891bd6825cSml return (err); 48901bd6825cSml } 48911bd6825cSml 48921bd6825cSml /* Blanking */ 48931bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 48941bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 48951bd6825cSml (char *)pr_val, 48961bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 48971bd6825cSml if (err) { 48981bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48991bd6825cSml "<== nxge_set_priv_prop: " 49001bd6825cSml "unable to set (%s)", pr_name)); 49011bd6825cSml err = EINVAL; 49021bd6825cSml } else { 49031bd6825cSml err = 0; 49041bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49051bd6825cSml "<== nxge_set_priv_prop: " 49061bd6825cSml "set (%s)", pr_name)); 49071bd6825cSml } 49081bd6825cSml 49091bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49101bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49111bd6825cSml pr_name, result)); 49121bd6825cSml 49131bd6825cSml return (err); 49141bd6825cSml } 49151bd6825cSml 49161bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 49171bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 49181bd6825cSml (char *)pr_val, 49191bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 49201bd6825cSml if (err) { 49211bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49221bd6825cSml "<== nxge_set_priv_prop: " 49231bd6825cSml "unable to set (%s)", pr_name)); 49241bd6825cSml err = EINVAL; 49251bd6825cSml } else { 49261bd6825cSml err = 0; 49271bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49281bd6825cSml "<== nxge_set_priv_prop: " 49291bd6825cSml "set (%s)", pr_name)); 49301bd6825cSml } 49311bd6825cSml 49321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49331bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49341bd6825cSml pr_name, result)); 49351bd6825cSml 49361bd6825cSml return (err); 49371bd6825cSml } 49381bd6825cSml 49391bd6825cSml /* Classification */ 49401bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 49411bd6825cSml if (pr_val == NULL) { 49421bd6825cSml err = EINVAL; 49431bd6825cSml return (err); 49441bd6825cSml } 49451bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49461bd6825cSml 49471bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49481bd6825cSml NULL, (char *)pr_val, 49491bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 49501bd6825cSml 49511bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49521bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49531bd6825cSml pr_name, result)); 49541bd6825cSml 49551bd6825cSml return (err); 49561bd6825cSml } 49571bd6825cSml 49581bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 49591bd6825cSml if (pr_val == NULL) { 49601bd6825cSml err = EINVAL; 49611bd6825cSml return (err); 49621bd6825cSml } 49631bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49641bd6825cSml 49651bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49661bd6825cSml NULL, (char *)pr_val, 49671bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 49681bd6825cSml 49691bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49701bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49711bd6825cSml pr_name, result)); 49721bd6825cSml 49731bd6825cSml return (err); 49741bd6825cSml } 49751bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 49761bd6825cSml if (pr_val == NULL) { 49771bd6825cSml err = EINVAL; 49781bd6825cSml return (err); 49791bd6825cSml } 49801bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49811bd6825cSml 49821bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49831bd6825cSml NULL, (char *)pr_val, 49841bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 49851bd6825cSml 49861bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49871bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49881bd6825cSml pr_name, result)); 49891bd6825cSml 49901bd6825cSml return (err); 49911bd6825cSml } 49921bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 49931bd6825cSml if (pr_val == NULL) { 49941bd6825cSml err = EINVAL; 49951bd6825cSml return (err); 49961bd6825cSml } 49971bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49981bd6825cSml 49991bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50001bd6825cSml NULL, (char *)pr_val, 50011bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 50021bd6825cSml 50031bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50041bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50051bd6825cSml pr_name, result)); 50061bd6825cSml 50071bd6825cSml return (err); 50081bd6825cSml } 50091bd6825cSml 50101bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 50111bd6825cSml if (pr_val == NULL) { 50121bd6825cSml err = EINVAL; 50131bd6825cSml return (err); 50141bd6825cSml } 50151bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50161bd6825cSml 50171bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50181bd6825cSml NULL, (char *)pr_val, 50191bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 50201bd6825cSml 50211bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50221bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50231bd6825cSml pr_name, result)); 50241bd6825cSml 50251bd6825cSml return (err); 50261bd6825cSml } 50271bd6825cSml 50281bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 50291bd6825cSml if (pr_val == NULL) { 50301bd6825cSml err = EINVAL; 50311bd6825cSml return (err); 50321bd6825cSml } 50331bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50341bd6825cSml 50351bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50361bd6825cSml NULL, (char *)pr_val, 50371bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 50381bd6825cSml 50391bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50401bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50411bd6825cSml pr_name, result)); 50421bd6825cSml 50431bd6825cSml return (err); 50441bd6825cSml } 50451bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 50461bd6825cSml if (pr_val == NULL) { 50471bd6825cSml err = EINVAL; 50481bd6825cSml return (err); 50491bd6825cSml } 50501bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50511bd6825cSml 50521bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50531bd6825cSml NULL, (char *)pr_val, 50541bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 50551bd6825cSml 50561bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50571bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50581bd6825cSml pr_name, result)); 50591bd6825cSml 50601bd6825cSml return (err); 50611bd6825cSml } 50621bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 50631bd6825cSml if (pr_val == NULL) { 50641bd6825cSml err = EINVAL; 50651bd6825cSml return (err); 50661bd6825cSml } 50671bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50681bd6825cSml 50691bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50701bd6825cSml NULL, (char *)pr_val, 50711bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 50721bd6825cSml 50731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50741bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50751bd6825cSml pr_name, result)); 50761bd6825cSml 50771bd6825cSml return (err); 50781bd6825cSml } 50791bd6825cSml 50801bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 50811bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 50821bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50831bd6825cSml "==> nxge_set_priv_prop: name %s (busy)", pr_name)); 50841bd6825cSml err = EBUSY; 50851bd6825cSml return (err); 50861bd6825cSml } 50871bd6825cSml if (pr_val == NULL) { 50881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50891bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 50901bd6825cSml err = EINVAL; 50911bd6825cSml return (err); 50921bd6825cSml } 50931bd6825cSml 50941bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50951bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50961bd6825cSml "<== nxge_set_priv_prop: name %s " 50971bd6825cSml "(lso %d pr_val %s value %d)", 50981bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 50991bd6825cSml 51001bd6825cSml if (result > 1 || result < 0) { 51011bd6825cSml err = EINVAL; 51021bd6825cSml } else { 51031bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 51041bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51051bd6825cSml "no change (%d %d)", 51061bd6825cSml nxgep->soft_lso_enable, result)); 51071bd6825cSml return (0); 51081bd6825cSml } 51091bd6825cSml } 51101bd6825cSml 51111bd6825cSml nxgep->soft_lso_enable = (int)result; 51121bd6825cSml 51131bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51141bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 51151bd6825cSml pr_name, result)); 51161bd6825cSml 51171bd6825cSml return (err); 51181bd6825cSml } 51194045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 51204045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51214045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 51224045d941Ssowmini return (err); 51234045d941Ssowmini } 51244045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 51254045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51264045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 51274045d941Ssowmini return (err); 51284045d941Ssowmini } 51291bd6825cSml 51301bd6825cSml return (EINVAL); 51311bd6825cSml } 51321bd6825cSml 51331bd6825cSml static int 51344045d941Ssowmini nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_flags, 51354045d941Ssowmini uint_t pr_valsize, void *pr_val) 51361bd6825cSml { 51371bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 51381bd6825cSml char valstr[MAXNAMELEN]; 51391bd6825cSml int err = EINVAL; 51401bd6825cSml uint_t strsize; 51414045d941Ssowmini boolean_t is_default = (pr_flags & DLD_DEFAULT); 51421bd6825cSml 51431bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51441bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 51451bd6825cSml 51461bd6825cSml /* function number */ 51471bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 51484045d941Ssowmini if (is_default) 51494045d941Ssowmini return (ENOTSUP); 51504045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51514045d941Ssowmini nxgep->function_num); 51521bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51531bd6825cSml "==> nxge_get_priv_prop: name %s " 51541bd6825cSml "(value %d valstr %s)", 51551bd6825cSml pr_name, nxgep->function_num, valstr)); 51561bd6825cSml 51571bd6825cSml err = 0; 51581bd6825cSml goto done; 51591bd6825cSml } 51601bd6825cSml 51611bd6825cSml /* Neptune firmware version */ 51621bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 51634045d941Ssowmini if (is_default) 51644045d941Ssowmini return (ENOTSUP); 51654045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 51664045d941Ssowmini nxgep->vpd_info.ver); 51671bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51681bd6825cSml "==> nxge_get_priv_prop: name %s " 51691bd6825cSml "(value %d valstr %s)", 51701bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 51711bd6825cSml 51721bd6825cSml err = 0; 51731bd6825cSml goto done; 51741bd6825cSml } 51751bd6825cSml 51761bd6825cSml /* port PHY mode */ 51771bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 51784045d941Ssowmini if (is_default) 51794045d941Ssowmini return (ENOTSUP); 51801bd6825cSml switch (nxgep->mac.portmode) { 51811bd6825cSml case PORT_1G_COPPER: 51824045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 51831bd6825cSml nxgep->hot_swappable_phy ? 51841bd6825cSml "[Hot Swappable]" : ""); 51851bd6825cSml break; 51861bd6825cSml case PORT_1G_FIBER: 51874045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 51881bd6825cSml nxgep->hot_swappable_phy ? 51891bd6825cSml "[hot swappable]" : ""); 51901bd6825cSml break; 51911bd6825cSml case PORT_10G_COPPER: 51924045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51934045d941Ssowmini "10G copper %s", 51941bd6825cSml nxgep->hot_swappable_phy ? 51951bd6825cSml "[hot swappable]" : ""); 51961bd6825cSml break; 51971bd6825cSml case PORT_10G_FIBER: 51984045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 51991bd6825cSml nxgep->hot_swappable_phy ? 52001bd6825cSml "[hot swappable]" : ""); 52011bd6825cSml break; 52021bd6825cSml case PORT_10G_SERDES: 52034045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52044045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 52051bd6825cSml "[hot swappable]" : ""); 52061bd6825cSml break; 52071bd6825cSml case PORT_1G_SERDES: 52084045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 52091bd6825cSml nxgep->hot_swappable_phy ? 52101bd6825cSml "[hot swappable]" : ""); 52111bd6825cSml break; 52121bd6825cSml case PORT_1G_RGMII_FIBER: 52134045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52144045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 52151bd6825cSml "[hot swappable]" : ""); 52161bd6825cSml break; 52171bd6825cSml case PORT_HSP_MODE: 52184045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5219c2d37b8bSml "phy not present[hot swappable]"); 52201bd6825cSml break; 52211bd6825cSml default: 52224045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 52231bd6825cSml nxgep->hot_swappable_phy ? 52241bd6825cSml "[hot swappable]" : ""); 52251bd6825cSml break; 52261bd6825cSml } 52271bd6825cSml 52281bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52291bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 52301bd6825cSml pr_name, valstr)); 52311bd6825cSml 52321bd6825cSml err = 0; 52331bd6825cSml goto done; 52341bd6825cSml } 52351bd6825cSml 52361bd6825cSml /* Hot swappable PHY */ 52371bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 52384045d941Ssowmini if (is_default) 52394045d941Ssowmini return (ENOTSUP); 52404045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 52411bd6825cSml nxgep->hot_swappable_phy ? 52421bd6825cSml "yes" : "no"); 52431bd6825cSml 52441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52451bd6825cSml "==> nxge_get_priv_prop: name %s " 52461bd6825cSml "(value %d valstr %s)", 52471bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 52481bd6825cSml 52491bd6825cSml err = 0; 52501bd6825cSml goto done; 52511bd6825cSml } 52521bd6825cSml 52531bd6825cSml 52541bd6825cSml /* accept jumbo */ 52551bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 52564045d941Ssowmini if (is_default) 52574045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 52584045d941Ssowmini else 52594045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52604045d941Ssowmini "%d", nxgep->mac.is_jumbo); 52611bd6825cSml err = 0; 52621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52631bd6825cSml "==> nxge_get_priv_prop: name %s (value %d (%d, %d))", 52641bd6825cSml pr_name, 52651bd6825cSml (uint32_t)param_arr[param_accept_jumbo].value, 52661bd6825cSml nxgep->mac.is_jumbo, 52671bd6825cSml nxge_jumbo_enable)); 52681bd6825cSml 52691bd6825cSml goto done; 52701bd6825cSml } 52711bd6825cSml 52721bd6825cSml /* Receive Interrupt Blanking Parameters */ 52731bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 52744045d941Ssowmini err = 0; 52754045d941Ssowmini if (is_default) { 52764045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52774045d941Ssowmini "%d", RXDMA_RCR_TO_DEFAULT); 52784045d941Ssowmini goto done; 52794045d941Ssowmini } 52804045d941Ssowmini 52814045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52824045d941Ssowmini nxgep->intr_timeout); 52831bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52841bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 52851bd6825cSml pr_name, 52861bd6825cSml (uint32_t)nxgep->intr_timeout)); 52871bd6825cSml goto done; 52881bd6825cSml } 52891bd6825cSml 52901bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 52914045d941Ssowmini err = 0; 52924045d941Ssowmini if (is_default) { 52934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52944045d941Ssowmini "%d", RXDMA_RCR_PTHRES_DEFAULT); 52954045d941Ssowmini goto done; 52964045d941Ssowmini } 52974045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52984045d941Ssowmini nxgep->intr_threshold); 52991bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53001bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53011bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 53021bd6825cSml 53031bd6825cSml goto done; 53041bd6825cSml } 53051bd6825cSml 53061bd6825cSml /* Classification and Load Distribution Configuration */ 53071bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 53084045d941Ssowmini if (is_default) { 53094045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53104045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53114045d941Ssowmini err = 0; 53124045d941Ssowmini goto done; 53134045d941Ssowmini } 53141bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53151bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 53161bd6825cSml 53174045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53181bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 53191bd6825cSml 53201bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53211bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53221bd6825cSml goto done; 53231bd6825cSml } 53241bd6825cSml 53251bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 53264045d941Ssowmini if (is_default) { 53274045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53284045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53294045d941Ssowmini err = 0; 53304045d941Ssowmini goto done; 53314045d941Ssowmini } 53321bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53331bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 53341bd6825cSml 53354045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53361bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 53371bd6825cSml 53381bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53391bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53401bd6825cSml goto done; 53411bd6825cSml } 53421bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 53434045d941Ssowmini if (is_default) { 53444045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53454045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53464045d941Ssowmini err = 0; 53474045d941Ssowmini goto done; 53484045d941Ssowmini } 53491bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53501bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 53511bd6825cSml 53524045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53531bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 53541bd6825cSml 53551bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53561bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53571bd6825cSml goto done; 53581bd6825cSml } 53591bd6825cSml 53601bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 53614045d941Ssowmini if (is_default) { 53624045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53634045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53644045d941Ssowmini err = 0; 53654045d941Ssowmini goto done; 53664045d941Ssowmini } 53671bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53681bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 53691bd6825cSml 53704045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53711bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 53721bd6825cSml 53731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53741bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53751bd6825cSml goto done; 53761bd6825cSml } 53771bd6825cSml 53781bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 53794045d941Ssowmini if (is_default) { 53804045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53814045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53824045d941Ssowmini err = 0; 53834045d941Ssowmini goto done; 53844045d941Ssowmini } 53851bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53861bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 53871bd6825cSml 53884045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53891bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 53901bd6825cSml 53911bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53921bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53931bd6825cSml goto done; 53941bd6825cSml } 53951bd6825cSml 53961bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 53974045d941Ssowmini if (is_default) { 53984045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53994045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54004045d941Ssowmini err = 0; 54014045d941Ssowmini goto done; 54024045d941Ssowmini } 54031bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54041bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 54051bd6825cSml 54064045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54071bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 54081bd6825cSml 54091bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54101bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54111bd6825cSml goto done; 54121bd6825cSml } 54131bd6825cSml 54141bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 54154045d941Ssowmini if (is_default) { 54164045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54174045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54184045d941Ssowmini err = 0; 54194045d941Ssowmini goto done; 54204045d941Ssowmini } 54211bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54221bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 54231bd6825cSml 54244045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54251bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 54261bd6825cSml 54271bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54281bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54291bd6825cSml goto done; 54301bd6825cSml } 54311bd6825cSml 54321bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 54334045d941Ssowmini if (is_default) { 54344045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54354045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54364045d941Ssowmini err = 0; 54374045d941Ssowmini goto done; 54384045d941Ssowmini } 54391bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54401bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 54411bd6825cSml 54424045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54431bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 54441bd6825cSml 54451bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54461bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54471bd6825cSml goto done; 54481bd6825cSml } 54491bd6825cSml 54501bd6825cSml /* Software LSO */ 54511bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 54524045d941Ssowmini if (is_default) { 54534045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54544045d941Ssowmini err = 0; 54554045d941Ssowmini goto done; 54564045d941Ssowmini } 54574045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 54584045d941Ssowmini "%d", nxgep->soft_lso_enable); 54591bd6825cSml err = 0; 54601bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54611bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 54621bd6825cSml pr_name, nxgep->soft_lso_enable)); 54631bd6825cSml 54641bd6825cSml goto done; 54651bd6825cSml } 54664045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 54674045d941Ssowmini err = 0; 54684045d941Ssowmini if (is_default || 54694045d941Ssowmini nxgep->param_arr[param_anar_10gfdx].value != 0) { 54704045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 54714045d941Ssowmini goto done; 54724045d941Ssowmini } else { 54734045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54744045d941Ssowmini goto done; 54754045d941Ssowmini } 54764045d941Ssowmini } 54774045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 54784045d941Ssowmini err = 0; 54794045d941Ssowmini if (is_default || 54804045d941Ssowmini nxgep->param_arr[param_anar_pause].value != 0) { 54814045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 54824045d941Ssowmini goto done; 54834045d941Ssowmini } else { 54844045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54854045d941Ssowmini goto done; 54864045d941Ssowmini } 54874045d941Ssowmini } 54881bd6825cSml 54891bd6825cSml done: 54901bd6825cSml if (err == 0) { 54911bd6825cSml strsize = (uint_t)strlen(valstr); 54921bd6825cSml if (pr_valsize < strsize) { 54931bd6825cSml err = ENOBUFS; 54941bd6825cSml } else { 54951bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 54961bd6825cSml } 54971bd6825cSml } 54981bd6825cSml 54991bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 55001bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 55011bd6825cSml return (err); 55021bd6825cSml } 55031bd6825cSml 550444961713Sgirish /* 550544961713Sgirish * Module loading and removing entry points. 550644961713Sgirish */ 550744961713Sgirish 5508*6f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 5509*6f157acbSml nodev, NULL, D_MP, NULL); 551044961713Sgirish 55112e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 551244961713Sgirish 551344961713Sgirish /* 551444961713Sgirish * Module linkage information for the kernel. 551544961713Sgirish */ 551644961713Sgirish static struct modldrv nxge_modldrv = { 551744961713Sgirish &mod_driverops, 551844961713Sgirish NXGE_DESC_VER, 551944961713Sgirish &nxge_dev_ops 552044961713Sgirish }; 552144961713Sgirish 552244961713Sgirish static struct modlinkage modlinkage = { 552344961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 552444961713Sgirish }; 552544961713Sgirish 552644961713Sgirish int 552744961713Sgirish _init(void) 552844961713Sgirish { 552944961713Sgirish int status; 553044961713Sgirish 553144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 553244961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 553344961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 553444961713Sgirish if (status != 0) { 553544961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 55364045d941Ssowmini "failed to init device soft state")); 553744961713Sgirish goto _init_exit; 553844961713Sgirish } 553944961713Sgirish status = mod_install(&modlinkage); 554044961713Sgirish if (status != 0) { 554144961713Sgirish ddi_soft_state_fini(&nxge_list); 554244961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 554344961713Sgirish goto _init_exit; 554444961713Sgirish } 554544961713Sgirish 554644961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 554744961713Sgirish 554844961713Sgirish _init_exit: 554944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 555044961713Sgirish 555144961713Sgirish return (status); 555244961713Sgirish } 555344961713Sgirish 555444961713Sgirish int 555544961713Sgirish _fini(void) 555644961713Sgirish { 555744961713Sgirish int status; 555844961713Sgirish 555944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 556044961713Sgirish 556144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5562a3c5bd6dSspeer 5563a3c5bd6dSspeer if (nxge_mblks_pending) 5564a3c5bd6dSspeer return (EBUSY); 5565a3c5bd6dSspeer 556644961713Sgirish status = mod_remove(&modlinkage); 556744961713Sgirish if (status != DDI_SUCCESS) { 556844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 55694045d941Ssowmini "Module removal failed 0x%08x", 55704045d941Ssowmini status)); 557144961713Sgirish goto _fini_exit; 557244961713Sgirish } 557344961713Sgirish 557444961713Sgirish mac_fini_ops(&nxge_dev_ops); 557544961713Sgirish 557644961713Sgirish ddi_soft_state_fini(&nxge_list); 557744961713Sgirish 557844961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 557944961713Sgirish _fini_exit: 558044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 558144961713Sgirish 558244961713Sgirish return (status); 558344961713Sgirish } 558444961713Sgirish 558544961713Sgirish int 558644961713Sgirish _info(struct modinfo *modinfop) 558744961713Sgirish { 558844961713Sgirish int status; 558944961713Sgirish 559044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 559144961713Sgirish status = mod_info(&modlinkage, modinfop); 559244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 559344961713Sgirish 559444961713Sgirish return (status); 559544961713Sgirish } 559644961713Sgirish 559744961713Sgirish /*ARGSUSED*/ 559844961713Sgirish static nxge_status_t 559944961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 560044961713Sgirish { 560144961713Sgirish 560244961713Sgirish int intr_types; 560344961713Sgirish int type = 0; 560444961713Sgirish int ddi_status = DDI_SUCCESS; 560544961713Sgirish nxge_status_t status = NXGE_OK; 560644961713Sgirish 560744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 560844961713Sgirish 560944961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 561044961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 561144961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 561244961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 561344961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 561444961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 561544961713Sgirish 561644961713Sgirish if (nxgep->niu_type == N2_NIU) { 561744961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 561844961713Sgirish } else if (nxge_msi_enable) { 561944961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 562044961713Sgirish } 562144961713Sgirish 562244961713Sgirish /* Get the supported interrupt types */ 562344961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 56244045d941Ssowmini != DDI_SUCCESS) { 562544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 56264045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 56274045d941Ssowmini ddi_status)); 562844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 562944961713Sgirish } 563044961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 563144961713Sgirish 563244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 56334045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 563444961713Sgirish 563544961713Sgirish /* 563644961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 563744961713Sgirish * nxge_msi_enable (1): 563844961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 563944961713Sgirish */ 564044961713Sgirish switch (nxge_msi_enable) { 564144961713Sgirish default: 564244961713Sgirish type = DDI_INTR_TYPE_FIXED; 564344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 56444045d941Ssowmini "use fixed (intx emulation) type %08x", 56454045d941Ssowmini type)); 564644961713Sgirish break; 564744961713Sgirish 564844961713Sgirish case 2: 564944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 56504045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 565144961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 565244961713Sgirish type = DDI_INTR_TYPE_MSIX; 565344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 56544045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 56554045d941Ssowmini type)); 565644961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 565744961713Sgirish type = DDI_INTR_TYPE_MSI; 565844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 56594045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 56604045d941Ssowmini type)); 566144961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 566244961713Sgirish type = DDI_INTR_TYPE_FIXED; 566344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 56644045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 56654045d941Ssowmini type)); 566644961713Sgirish } 566744961713Sgirish break; 566844961713Sgirish 566944961713Sgirish case 1: 567044961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 567144961713Sgirish type = DDI_INTR_TYPE_MSI; 567244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 56734045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 56744045d941Ssowmini type)); 567544961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 567644961713Sgirish type = DDI_INTR_TYPE_MSIX; 567744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 56784045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 56794045d941Ssowmini type)); 568044961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 568144961713Sgirish type = DDI_INTR_TYPE_FIXED; 568244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 56834045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 56844045d941Ssowmini type)); 568544961713Sgirish } 568644961713Sgirish } 568744961713Sgirish 568844961713Sgirish nxgep->nxge_intr_type.intr_type = type; 568944961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 56904045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 56914045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 569244961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 569344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 56944045d941Ssowmini " nxge_add_intrs: " 56954045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 56964045d941Ssowmini status)); 569744961713Sgirish return (status); 569844961713Sgirish } else { 569944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57004045d941Ssowmini "interrupts registered : type %d", type)); 570144961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 570244961713Sgirish 570344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 57044045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 57054045d941Ssowmini "intr type 0x%x\n", type)); 570644961713Sgirish 570744961713Sgirish return (status); 570844961713Sgirish } 570944961713Sgirish } 571044961713Sgirish 571144961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 571244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 57134045d941Ssowmini "failed to register interrupts")); 571444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 571544961713Sgirish } 571644961713Sgirish 571744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 571844961713Sgirish return (status); 571944961713Sgirish } 572044961713Sgirish 572144961713Sgirish /*ARGSUSED*/ 572244961713Sgirish static nxge_status_t 572344961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep) 572444961713Sgirish { 572544961713Sgirish 572644961713Sgirish int ddi_status = DDI_SUCCESS; 572744961713Sgirish nxge_status_t status = NXGE_OK; 572844961713Sgirish 572944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs")); 573044961713Sgirish 573144961713Sgirish nxgep->resched_id = NULL; 573244961713Sgirish nxgep->resched_running = B_FALSE; 573344961713Sgirish ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW, 57344045d941Ssowmini &nxgep->resched_id, 57354045d941Ssowmini NULL, NULL, nxge_reschedule, (caddr_t)nxgep); 573644961713Sgirish if (ddi_status != DDI_SUCCESS) { 573744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: " 57384045d941Ssowmini "ddi_add_softintrs failed: status 0x%08x", 57394045d941Ssowmini ddi_status)); 574044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 574144961713Sgirish } 574244961713Sgirish 574344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs")); 574444961713Sgirish 574544961713Sgirish return (status); 574644961713Sgirish } 574744961713Sgirish 574844961713Sgirish static nxge_status_t 574944961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 575044961713Sgirish { 575144961713Sgirish int intr_type; 575244961713Sgirish p_nxge_intr_t intrp; 575344961713Sgirish 575444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 575544961713Sgirish 575644961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 575744961713Sgirish intr_type = intrp->intr_type; 575844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 57594045d941Ssowmini intr_type)); 576044961713Sgirish 576144961713Sgirish switch (intr_type) { 576244961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 576344961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 576444961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 576544961713Sgirish 576644961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 576744961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 576844961713Sgirish 576944961713Sgirish default: 577044961713Sgirish return (NXGE_ERROR); 577144961713Sgirish } 577244961713Sgirish } 577344961713Sgirish 577444961713Sgirish 577544961713Sgirish /*ARGSUSED*/ 577644961713Sgirish static nxge_status_t 577744961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 577844961713Sgirish { 577944961713Sgirish dev_info_t *dip = nxgep->dip; 578044961713Sgirish p_nxge_ldg_t ldgp; 578144961713Sgirish p_nxge_intr_t intrp; 578244961713Sgirish uint_t *inthandler; 578344961713Sgirish void *arg1, *arg2; 578444961713Sgirish int behavior; 5785ec090658Sml int nintrs, navail, nrequest; 578644961713Sgirish int nactual, nrequired; 578744961713Sgirish int inum = 0; 578844961713Sgirish int x, y; 578944961713Sgirish int ddi_status = DDI_SUCCESS; 579044961713Sgirish nxge_status_t status = NXGE_OK; 579144961713Sgirish 579244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 579344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 579444961713Sgirish intrp->start_inum = 0; 579544961713Sgirish 579644961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 579744961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 579844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57994045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 58004045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 580144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 580244961713Sgirish } 580344961713Sgirish 580444961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 580544961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 580644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58074045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 58084045d941Ssowmini "nintrs: %d", ddi_status, navail)); 580944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 581044961713Sgirish } 581144961713Sgirish 581244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 58134045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 58144045d941Ssowmini nintrs, navail)); 581544961713Sgirish 5816ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5817ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5818ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5819ec090658Sml if (nrequest < navail) { 5820ec090658Sml navail = nrequest; 5821ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5822ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5823ec090658Sml "navail %d (nrequest %d)", 5824ec090658Sml nintrs, navail, nrequest)); 5825ec090658Sml } 5826ec090658Sml } 5827ec090658Sml 582844961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 582944961713Sgirish /* MSI must be power of 2 */ 583044961713Sgirish if ((navail & 16) == 16) { 583144961713Sgirish navail = 16; 583244961713Sgirish } else if ((navail & 8) == 8) { 583344961713Sgirish navail = 8; 583444961713Sgirish } else if ((navail & 4) == 4) { 583544961713Sgirish navail = 4; 583644961713Sgirish } else if ((navail & 2) == 2) { 583744961713Sgirish navail = 2; 583844961713Sgirish } else { 583944961713Sgirish navail = 1; 584044961713Sgirish } 584144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 58424045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 58434045d941Ssowmini "navail %d", nintrs, navail)); 584444961713Sgirish } 584544961713Sgirish 584644961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 58474045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 584844961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 584944961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 585044961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 58514045d941Ssowmini navail, &nactual, behavior); 585244961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 585344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58544045d941Ssowmini " ddi_intr_alloc() failed: %d", 58554045d941Ssowmini ddi_status)); 585644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 585744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 585844961713Sgirish } 585944961713Sgirish 586044961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 58614045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 586244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58634045d941Ssowmini " ddi_intr_get_pri() failed: %d", 58644045d941Ssowmini ddi_status)); 586544961713Sgirish /* Free already allocated interrupts */ 586644961713Sgirish for (y = 0; y < nactual; y++) { 586744961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 586844961713Sgirish } 586944961713Sgirish 587044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 587144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 587244961713Sgirish } 587344961713Sgirish 587444961713Sgirish nrequired = 0; 587544961713Sgirish switch (nxgep->niu_type) { 587644961713Sgirish default: 587744961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 587844961713Sgirish break; 587944961713Sgirish 588044961713Sgirish case N2_NIU: 588144961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 588244961713Sgirish break; 588344961713Sgirish } 588444961713Sgirish 588544961713Sgirish if (status != NXGE_OK) { 588644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58874045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 58884045d941Ssowmini "failed: 0x%x", status)); 588944961713Sgirish /* Free already allocated interrupts */ 589044961713Sgirish for (y = 0; y < nactual; y++) { 589144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 589244961713Sgirish } 589344961713Sgirish 589444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 589544961713Sgirish return (status); 589644961713Sgirish } 589744961713Sgirish 589844961713Sgirish ldgp = nxgep->ldgvp->ldgp; 589944961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 590044961713Sgirish ldgp->vector = (uint8_t)x; 590144961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 590244961713Sgirish arg1 = ldgp->ldvp; 590344961713Sgirish arg2 = nxgep; 590444961713Sgirish if (ldgp->nldvs == 1) { 590544961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 590644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59074045d941Ssowmini "nxge_add_intrs_adv_type: " 59084045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59094045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 59104045d941Ssowmini arg1, arg2, 59114045d941Ssowmini x, ldgp->intdata)); 591244961713Sgirish } else if (ldgp->nldvs > 1) { 591344961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 591444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59154045d941Ssowmini "nxge_add_intrs_adv_type: " 59164045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59174045d941Ssowmini "nldevs %d int handler " 59184045d941Ssowmini "(entry %d intdata 0x%x)\n", 59194045d941Ssowmini arg1, arg2, 59204045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 592144961713Sgirish } 592244961713Sgirish 592344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59244045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 59254045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 592644961713Sgirish 592744961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 59284045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 59294045d941Ssowmini != DDI_SUCCESS) { 593044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59314045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 59324045d941Ssowmini "status 0x%x", x, ddi_status)); 593344961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 593444961713Sgirish (void) ddi_intr_remove_handler( 59354045d941Ssowmini intrp->htable[y]); 593644961713Sgirish } 593744961713Sgirish /* Free already allocated intr */ 593844961713Sgirish for (y = 0; y < nactual; y++) { 593944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 594044961713Sgirish } 594144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 594244961713Sgirish 594344961713Sgirish (void) nxge_ldgv_uninit(nxgep); 594444961713Sgirish 594544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 594644961713Sgirish } 594744961713Sgirish intrp->intr_added++; 594844961713Sgirish } 594944961713Sgirish 595044961713Sgirish intrp->msi_intx_cnt = nactual; 595144961713Sgirish 595244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 59534045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 59544045d941Ssowmini navail, nactual, 59554045d941Ssowmini intrp->msi_intx_cnt, 59564045d941Ssowmini intrp->intr_added)); 595744961713Sgirish 595844961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 595944961713Sgirish 596044961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 596144961713Sgirish 596244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 596344961713Sgirish 596444961713Sgirish return (status); 596544961713Sgirish } 596644961713Sgirish 596744961713Sgirish /*ARGSUSED*/ 596844961713Sgirish static nxge_status_t 596944961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 597044961713Sgirish { 597144961713Sgirish dev_info_t *dip = nxgep->dip; 597244961713Sgirish p_nxge_ldg_t ldgp; 597344961713Sgirish p_nxge_intr_t intrp; 597444961713Sgirish uint_t *inthandler; 597544961713Sgirish void *arg1, *arg2; 597644961713Sgirish int behavior; 597744961713Sgirish int nintrs, navail; 597844961713Sgirish int nactual, nrequired; 597944961713Sgirish int inum = 0; 598044961713Sgirish int x, y; 598144961713Sgirish int ddi_status = DDI_SUCCESS; 598244961713Sgirish nxge_status_t status = NXGE_OK; 598344961713Sgirish 598444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 598544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 598644961713Sgirish intrp->start_inum = 0; 598744961713Sgirish 598844961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 598944961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 599044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59914045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 59924045d941Ssowmini "nintrs: %d", status, nintrs)); 599344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 599444961713Sgirish } 599544961713Sgirish 599644961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 599744961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 599844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59994045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 60004045d941Ssowmini "nintrs: %d", ddi_status, navail)); 600144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 600244961713Sgirish } 600344961713Sgirish 600444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60054045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 60064045d941Ssowmini nintrs, navail)); 600744961713Sgirish 600844961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 60094045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 601044961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 601144961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 601244961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 60134045d941Ssowmini navail, &nactual, behavior); 601444961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 601544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60164045d941Ssowmini " ddi_intr_alloc() failed: %d", 60174045d941Ssowmini ddi_status)); 601844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 601944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 602044961713Sgirish } 602144961713Sgirish 602244961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 60234045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 602444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60254045d941Ssowmini " ddi_intr_get_pri() failed: %d", 60264045d941Ssowmini ddi_status)); 602744961713Sgirish /* Free already allocated interrupts */ 602844961713Sgirish for (y = 0; y < nactual; y++) { 602944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 603044961713Sgirish } 603144961713Sgirish 603244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 603344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 603444961713Sgirish } 603544961713Sgirish 603644961713Sgirish nrequired = 0; 603744961713Sgirish switch (nxgep->niu_type) { 603844961713Sgirish default: 603944961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 604044961713Sgirish break; 604144961713Sgirish 604244961713Sgirish case N2_NIU: 604344961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 604444961713Sgirish break; 604544961713Sgirish } 604644961713Sgirish 604744961713Sgirish if (status != NXGE_OK) { 604844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60494045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 60504045d941Ssowmini "failed: 0x%x", status)); 605144961713Sgirish /* Free already allocated interrupts */ 605244961713Sgirish for (y = 0; y < nactual; y++) { 605344961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 605444961713Sgirish } 605544961713Sgirish 605644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 605744961713Sgirish return (status); 605844961713Sgirish } 605944961713Sgirish 606044961713Sgirish ldgp = nxgep->ldgvp->ldgp; 606144961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 606244961713Sgirish ldgp->vector = (uint8_t)x; 606344961713Sgirish if (nxgep->niu_type != N2_NIU) { 606444961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 606544961713Sgirish } 606644961713Sgirish 606744961713Sgirish arg1 = ldgp->ldvp; 606844961713Sgirish arg2 = nxgep; 606944961713Sgirish if (ldgp->nldvs == 1) { 607044961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 607144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60724045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 60734045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 60744045d941Ssowmini "arg1 $%p arg2 $%p\n", 60754045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 60764045d941Ssowmini arg1, arg2)); 607744961713Sgirish } else if (ldgp->nldvs > 1) { 607844961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 607944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60804045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 60814045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 60824045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 60834045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 60844045d941Ssowmini arg1, arg2)); 608544961713Sgirish } 608644961713Sgirish 608744961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 60884045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 60894045d941Ssowmini != DDI_SUCCESS) { 609044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60914045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 60924045d941Ssowmini "status 0x%x", x, ddi_status)); 609344961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 609444961713Sgirish (void) ddi_intr_remove_handler( 60954045d941Ssowmini intrp->htable[y]); 609644961713Sgirish } 609744961713Sgirish for (y = 0; y < nactual; y++) { 609844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 609944961713Sgirish } 610044961713Sgirish /* Free already allocated intr */ 610144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 610244961713Sgirish 610344961713Sgirish (void) nxge_ldgv_uninit(nxgep); 610444961713Sgirish 610544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 610644961713Sgirish } 610744961713Sgirish intrp->intr_added++; 610844961713Sgirish } 610944961713Sgirish 611044961713Sgirish intrp->msi_intx_cnt = nactual; 611144961713Sgirish 611244961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 611344961713Sgirish 611444961713Sgirish status = nxge_intr_ldgv_init(nxgep); 611544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 611644961713Sgirish 611744961713Sgirish return (status); 611844961713Sgirish } 611944961713Sgirish 612044961713Sgirish static void 612144961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 612244961713Sgirish { 612344961713Sgirish int i, inum; 612444961713Sgirish p_nxge_intr_t intrp; 612544961713Sgirish 612644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 612744961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 612844961713Sgirish if (!intrp->intr_registered) { 612944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61304045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 613144961713Sgirish return; 613244961713Sgirish } 613344961713Sgirish 613444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 613544961713Sgirish 613644961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 613744961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 61384045d941Ssowmini intrp->intr_added); 613944961713Sgirish } else { 614044961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 614144961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 614244961713Sgirish } 614344961713Sgirish } 614444961713Sgirish 614544961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 614644961713Sgirish if (intrp->htable[inum]) { 614744961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 614844961713Sgirish } 614944961713Sgirish } 615044961713Sgirish 615144961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 615244961713Sgirish if (intrp->htable[inum]) { 615344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 61544045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 61554045d941Ssowmini "msi_intx_cnt %d intr_added %d", 61564045d941Ssowmini inum, 61574045d941Ssowmini intrp->msi_intx_cnt, 61584045d941Ssowmini intrp->intr_added)); 615944961713Sgirish 616044961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 616144961713Sgirish } 616244961713Sgirish } 616344961713Sgirish 616444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 616544961713Sgirish intrp->intr_registered = B_FALSE; 616644961713Sgirish intrp->intr_enabled = B_FALSE; 616744961713Sgirish intrp->msi_intx_cnt = 0; 616844961713Sgirish intrp->intr_added = 0; 616944961713Sgirish 6170a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6171a3c5bd6dSspeer 6172ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6173ec090658Sml "#msix-request"); 6174ec090658Sml 617544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 617644961713Sgirish } 617744961713Sgirish 617844961713Sgirish /*ARGSUSED*/ 617944961713Sgirish static void 618044961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep) 618144961713Sgirish { 618244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs")); 618344961713Sgirish if (nxgep->resched_id) { 618444961713Sgirish ddi_remove_softintr(nxgep->resched_id); 618544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61864045d941Ssowmini "==> nxge_remove_soft_intrs: removed")); 618744961713Sgirish nxgep->resched_id = NULL; 618844961713Sgirish } 618944961713Sgirish 619044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs")); 619144961713Sgirish } 619244961713Sgirish 619344961713Sgirish /*ARGSUSED*/ 619444961713Sgirish static void 619544961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 619644961713Sgirish { 619744961713Sgirish p_nxge_intr_t intrp; 619844961713Sgirish int i; 619944961713Sgirish int status; 620044961713Sgirish 620144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 620244961713Sgirish 620344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 620444961713Sgirish 620544961713Sgirish if (!intrp->intr_registered) { 620644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 62074045d941Ssowmini "interrupts are not registered")); 620844961713Sgirish return; 620944961713Sgirish } 621044961713Sgirish 621144961713Sgirish if (intrp->intr_enabled) { 621244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62134045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 621444961713Sgirish return; 621544961713Sgirish } 621644961713Sgirish 621744961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 621844961713Sgirish status = ddi_intr_block_enable(intrp->htable, 62194045d941Ssowmini intrp->intr_added); 622044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62214045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 62224045d941Ssowmini status, intrp->intr_added)); 622344961713Sgirish } else { 622444961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 622544961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 622644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62274045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 62284045d941Ssowmini "total inums %d enable inum #%d\n", 62294045d941Ssowmini status, intrp->intr_added, i)); 623044961713Sgirish if (status == DDI_SUCCESS) { 623144961713Sgirish intrp->intr_enabled = B_TRUE; 623244961713Sgirish } 623344961713Sgirish } 623444961713Sgirish } 623544961713Sgirish 623644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 623744961713Sgirish } 623844961713Sgirish 623944961713Sgirish /*ARGSUSED*/ 624044961713Sgirish static void 624144961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 624244961713Sgirish { 624344961713Sgirish p_nxge_intr_t intrp; 624444961713Sgirish int i; 624544961713Sgirish 624644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 624744961713Sgirish 624844961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 624944961713Sgirish 625044961713Sgirish if (!intrp->intr_registered) { 625144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 62524045d941Ssowmini "interrupts are not registered")); 625344961713Sgirish return; 625444961713Sgirish } 625544961713Sgirish 625644961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 625744961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 62584045d941Ssowmini intrp->intr_added); 625944961713Sgirish } else { 626044961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 626144961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 626244961713Sgirish } 626344961713Sgirish } 626444961713Sgirish 626544961713Sgirish intrp->intr_enabled = B_FALSE; 626644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 626744961713Sgirish } 626844961713Sgirish 626944961713Sgirish static nxge_status_t 627044961713Sgirish nxge_mac_register(p_nxge_t nxgep) 627144961713Sgirish { 627244961713Sgirish mac_register_t *macp; 627344961713Sgirish int status; 627444961713Sgirish 627544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 627644961713Sgirish 627744961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 627844961713Sgirish return (NXGE_ERROR); 627944961713Sgirish 628044961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 628144961713Sgirish macp->m_driver = nxgep; 628244961713Sgirish macp->m_dip = nxgep->dip; 628344961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 628444961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 628544961713Sgirish macp->m_min_sdu = 0; 62861bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 62871bd6825cSml NXGE_EHEADER_VLAN_CRC; 62881bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6289d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 62904045d941Ssowmini macp->m_priv_props = nxge_priv_props; 62914045d941Ssowmini macp->m_priv_prop_count = NXGE_MAX_PRIV_PROPS; 629244961713Sgirish 62931bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62941bd6825cSml "==> nxge_mac_register: instance %d " 62951bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 62961bd6825cSml nxgep->instance, 62971bd6825cSml macp->m_max_sdu, macp->m_margin, 62981bd6825cSml nxgep->mac.maxframesize, 62991bd6825cSml NXGE_EHEADER_VLAN_CRC)); 63001bd6825cSml 630144961713Sgirish status = mac_register(macp, &nxgep->mach); 630244961713Sgirish mac_free(macp); 630344961713Sgirish 630444961713Sgirish if (status != 0) { 630544961713Sgirish cmn_err(CE_WARN, 63064045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 63074045d941Ssowmini status, nxgep->instance); 630844961713Sgirish return (NXGE_ERROR); 630944961713Sgirish } 631044961713Sgirish 631144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 63124045d941Ssowmini "(instance %d)", nxgep->instance)); 631344961713Sgirish 631444961713Sgirish return (NXGE_OK); 631544961713Sgirish } 631644961713Sgirish 631744961713Sgirish void 631844961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 631944961713Sgirish { 632044961713Sgirish ssize_t size; 632144961713Sgirish mblk_t *nmp; 632244961713Sgirish uint8_t blk_id; 632344961713Sgirish uint8_t chan; 632444961713Sgirish uint32_t err_id; 632544961713Sgirish err_inject_t *eip; 632644961713Sgirish 632744961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 632844961713Sgirish 632944961713Sgirish size = 1024; 633044961713Sgirish nmp = mp->b_cont; 633144961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 633244961713Sgirish blk_id = eip->blk_id; 633344961713Sgirish err_id = eip->err_id; 633444961713Sgirish chan = eip->chan; 633544961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 633644961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 633744961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 633844961713Sgirish switch (blk_id) { 633944961713Sgirish case MAC_BLK_ID: 634044961713Sgirish break; 634144961713Sgirish case TXMAC_BLK_ID: 634244961713Sgirish break; 634344961713Sgirish case RXMAC_BLK_ID: 634444961713Sgirish break; 634544961713Sgirish case MIF_BLK_ID: 634644961713Sgirish break; 634744961713Sgirish case IPP_BLK_ID: 634844961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 634944961713Sgirish break; 635044961713Sgirish case TXC_BLK_ID: 635144961713Sgirish nxge_txc_inject_err(nxgep, err_id); 635244961713Sgirish break; 635344961713Sgirish case TXDMA_BLK_ID: 635444961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 635544961713Sgirish break; 635644961713Sgirish case RXDMA_BLK_ID: 635744961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 635844961713Sgirish break; 635944961713Sgirish case ZCP_BLK_ID: 636044961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 636144961713Sgirish break; 636244961713Sgirish case ESPC_BLK_ID: 636344961713Sgirish break; 636444961713Sgirish case FFLP_BLK_ID: 636544961713Sgirish break; 636644961713Sgirish case PHY_BLK_ID: 636744961713Sgirish break; 636844961713Sgirish case ETHER_SERDES_BLK_ID: 636944961713Sgirish break; 637044961713Sgirish case PCIE_SERDES_BLK_ID: 637144961713Sgirish break; 637244961713Sgirish case VIR_BLK_ID: 637344961713Sgirish break; 637444961713Sgirish } 637544961713Sgirish 637644961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 637744961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 637844961713Sgirish 637944961713Sgirish miocack(wq, mp, (int)size, 0); 638044961713Sgirish } 638144961713Sgirish 638244961713Sgirish static int 638344961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 638444961713Sgirish { 638544961713Sgirish p_nxge_hw_list_t hw_p; 638644961713Sgirish dev_info_t *p_dip; 638744961713Sgirish 638844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 638944961713Sgirish 639044961713Sgirish p_dip = nxgep->p_dip; 639144961713Sgirish MUTEX_ENTER(&nxge_common_lock); 639244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 63934045d941Ssowmini "==> nxge_init_common_dev:func # %d", 63944045d941Ssowmini nxgep->function_num)); 639544961713Sgirish /* 639644961713Sgirish * Loop through existing per neptune hardware list. 639744961713Sgirish */ 639844961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 639944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64004045d941Ssowmini "==> nxge_init_common_device:func # %d " 64014045d941Ssowmini "hw_p $%p parent dip $%p", 64024045d941Ssowmini nxgep->function_num, 64034045d941Ssowmini hw_p, 64044045d941Ssowmini p_dip)); 640544961713Sgirish if (hw_p->parent_devp == p_dip) { 640644961713Sgirish nxgep->nxge_hw_p = hw_p; 640744961713Sgirish hw_p->ndevs++; 640844961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 640944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64104045d941Ssowmini "==> nxge_init_common_device:func # %d " 64114045d941Ssowmini "hw_p $%p parent dip $%p " 64124045d941Ssowmini "ndevs %d (found)", 64134045d941Ssowmini nxgep->function_num, 64144045d941Ssowmini hw_p, 64154045d941Ssowmini p_dip, 64164045d941Ssowmini hw_p->ndevs)); 641744961713Sgirish break; 641844961713Sgirish } 641944961713Sgirish } 642044961713Sgirish 642144961713Sgirish if (hw_p == NULL) { 642244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64234045d941Ssowmini "==> nxge_init_common_device:func # %d " 64244045d941Ssowmini "parent dip $%p (new)", 64254045d941Ssowmini nxgep->function_num, 64264045d941Ssowmini p_dip)); 642744961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 642844961713Sgirish hw_p->parent_devp = p_dip; 642944961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 643044961713Sgirish nxgep->nxge_hw_p = hw_p; 643144961713Sgirish hw_p->ndevs++; 643244961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 643344961713Sgirish hw_p->next = nxge_hw_list; 643459ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 643559ac0c16Sdavemq hw_p->niu_type = N2_NIU; 643659ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 643759ac0c16Sdavemq } else { 643859ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 64392e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 644059ac0c16Sdavemq } 644144961713Sgirish 644244961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 644344961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 644444961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 644544961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 644644961713Sgirish 644744961713Sgirish nxge_hw_list = hw_p; 644859ac0c16Sdavemq 644959ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 645044961713Sgirish } 645144961713Sgirish 645244961713Sgirish MUTEX_EXIT(&nxge_common_lock); 645359ac0c16Sdavemq 64542e59129aSraghus nxgep->platform_type = hw_p->platform_type; 645559ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 645659ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 645759ac0c16Sdavemq } 645859ac0c16Sdavemq 645944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64604045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 64614045d941Ssowmini nxge_hw_list)); 646244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 646344961713Sgirish 646444961713Sgirish return (NXGE_OK); 646544961713Sgirish } 646644961713Sgirish 646744961713Sgirish static void 646844961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 646944961713Sgirish { 647044961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 647144961713Sgirish dev_info_t *p_dip; 647244961713Sgirish 647344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 647444961713Sgirish if (nxgep->nxge_hw_p == NULL) { 647544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64764045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 647744961713Sgirish return; 647844961713Sgirish } 647944961713Sgirish 648044961713Sgirish MUTEX_ENTER(&nxge_common_lock); 648144961713Sgirish h_hw_p = nxge_hw_list; 648244961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 648344961713Sgirish p_dip = hw_p->parent_devp; 648444961713Sgirish if (nxgep->nxge_hw_p == hw_p && 64854045d941Ssowmini p_dip == nxgep->p_dip && 64864045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 64874045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 648844961713Sgirish 648944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64904045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 64914045d941Ssowmini "hw_p $%p parent dip $%p " 64924045d941Ssowmini "ndevs %d (found)", 64934045d941Ssowmini nxgep->function_num, 64944045d941Ssowmini hw_p, 64954045d941Ssowmini p_dip, 64964045d941Ssowmini hw_p->ndevs)); 649744961713Sgirish 649844961713Sgirish if (hw_p->ndevs) { 649944961713Sgirish hw_p->ndevs--; 650044961713Sgirish } 650144961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 650244961713Sgirish if (!hw_p->ndevs) { 650344961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 650444961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 650544961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 650644961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 650744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65084045d941Ssowmini "==> nxge_uninit_common_device: " 65094045d941Ssowmini "func # %d " 65104045d941Ssowmini "hw_p $%p parent dip $%p " 65114045d941Ssowmini "ndevs %d (last)", 65124045d941Ssowmini nxgep->function_num, 65134045d941Ssowmini hw_p, 65144045d941Ssowmini p_dip, 65154045d941Ssowmini hw_p->ndevs)); 651644961713Sgirish 6517678453a8Sspeer nxge_hio_uninit(nxgep); 6518678453a8Sspeer 651944961713Sgirish if (hw_p == nxge_hw_list) { 652044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65214045d941Ssowmini "==> nxge_uninit_common_device:" 65224045d941Ssowmini "remove head func # %d " 65234045d941Ssowmini "hw_p $%p parent dip $%p " 65244045d941Ssowmini "ndevs %d (head)", 65254045d941Ssowmini nxgep->function_num, 65264045d941Ssowmini hw_p, 65274045d941Ssowmini p_dip, 65284045d941Ssowmini hw_p->ndevs)); 652944961713Sgirish nxge_hw_list = hw_p->next; 653044961713Sgirish } else { 653144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65324045d941Ssowmini "==> nxge_uninit_common_device:" 65334045d941Ssowmini "remove middle func # %d " 65344045d941Ssowmini "hw_p $%p parent dip $%p " 65354045d941Ssowmini "ndevs %d (middle)", 65364045d941Ssowmini nxgep->function_num, 65374045d941Ssowmini hw_p, 65384045d941Ssowmini p_dip, 65394045d941Ssowmini hw_p->ndevs)); 654044961713Sgirish h_hw_p->next = hw_p->next; 654144961713Sgirish } 654244961713Sgirish 6543678453a8Sspeer nxgep->nxge_hw_p = NULL; 654444961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 654544961713Sgirish } 654644961713Sgirish break; 654744961713Sgirish } else { 654844961713Sgirish h_hw_p = hw_p; 654944961713Sgirish } 655044961713Sgirish } 655144961713Sgirish 655244961713Sgirish MUTEX_EXIT(&nxge_common_lock); 655344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65544045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 65554045d941Ssowmini nxge_hw_list)); 655644961713Sgirish 655744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 655844961713Sgirish } 655959ac0c16Sdavemq 656059ac0c16Sdavemq /* 65612e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 656259ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 656359ac0c16Sdavemq */ 656459ac0c16Sdavemq 656559ac0c16Sdavemq int 65662e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 656759ac0c16Sdavemq { 656859ac0c16Sdavemq int nports = 0; 656959ac0c16Sdavemq 65702e59129aSraghus switch (nxgep->niu_type) { 657159ac0c16Sdavemq case N2_NIU: 657259ac0c16Sdavemq case NEPTUNE_2_10GF: 657359ac0c16Sdavemq nports = 2; 657459ac0c16Sdavemq break; 657559ac0c16Sdavemq case NEPTUNE_4_1GC: 657659ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 657759ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 657859ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 657959a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 658059ac0c16Sdavemq nports = 4; 658159ac0c16Sdavemq break; 658259ac0c16Sdavemq default: 65832e59129aSraghus switch (nxgep->platform_type) { 65842e59129aSraghus case P_NEPTUNE_NIU: 65852e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 65862e59129aSraghus nports = 2; 65872e59129aSraghus break; 65882e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 65892e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 65902e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 6591d81011f0Ssbehera case P_NEPTUNE_ALONSO: 65922e59129aSraghus nports = 4; 65932e59129aSraghus break; 65942e59129aSraghus default: 65952e59129aSraghus break; 65962e59129aSraghus } 659759ac0c16Sdavemq break; 659859ac0c16Sdavemq } 659959ac0c16Sdavemq 660059ac0c16Sdavemq return (nports); 660159ac0c16Sdavemq } 6602ec090658Sml 6603ec090658Sml /* 6604ec090658Sml * The following two functions are to support 6605ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6606ec090658Sml */ 6607ec090658Sml static int 6608ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6609ec090658Sml { 6610ec090658Sml int nmsi; 6611ec090658Sml extern int ncpus; 6612ec090658Sml 6613ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6614ec090658Sml 6615ec090658Sml switch (nxgep->mac.portmode) { 6616ec090658Sml case PORT_10G_COPPER: 6617ec090658Sml case PORT_10G_FIBER: 6618ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6619ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6620ec090658Sml /* 6621ec090658Sml * The maximum MSI-X requested will be 8. 6622ec090658Sml * If the # of CPUs is less than 8, we will reqeust 6623ec090658Sml * # MSI-X based on the # of CPUs. 6624ec090658Sml */ 6625ec090658Sml if (ncpus >= NXGE_MSIX_REQUEST_10G) { 6626ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6627ec090658Sml } else { 6628ec090658Sml nmsi = ncpus; 6629ec090658Sml } 6630ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6631ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6632ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6633ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6634ec090658Sml break; 6635ec090658Sml 6636ec090658Sml default: 6637ec090658Sml nmsi = NXGE_MSIX_REQUEST_1G; 6638ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6639ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 6640ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6641ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6642ec090658Sml break; 6643ec090658Sml } 6644ec090658Sml 6645ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 6646ec090658Sml return (nmsi); 6647ec090658Sml } 66484045d941Ssowmini 66494045d941Ssowmini /* ARGSUSED */ 66504045d941Ssowmini static int 66514045d941Ssowmini nxge_get_def_val(nxge_t *nxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 66524045d941Ssowmini void *pr_val) 66534045d941Ssowmini { 66544045d941Ssowmini int err = 0; 66554045d941Ssowmini link_flowctrl_t fl; 66564045d941Ssowmini 66574045d941Ssowmini switch (pr_num) { 66584045d941Ssowmini case DLD_PROP_AUTONEG: 66594045d941Ssowmini *(uint8_t *)pr_val = 1; 66604045d941Ssowmini break; 66614045d941Ssowmini case DLD_PROP_FLOWCTRL: 66624045d941Ssowmini if (pr_valsize < sizeof (link_flowctrl_t)) 66634045d941Ssowmini return (EINVAL); 66644045d941Ssowmini fl = LINK_FLOWCTRL_RX; 66654045d941Ssowmini bcopy(&fl, pr_val, sizeof (fl)); 66664045d941Ssowmini break; 66674045d941Ssowmini case DLD_PROP_ADV_1000FDX_CAP: 66684045d941Ssowmini case DLD_PROP_EN_1000FDX_CAP: 66694045d941Ssowmini *(uint8_t *)pr_val = 1; 66704045d941Ssowmini break; 66714045d941Ssowmini case DLD_PROP_ADV_100FDX_CAP: 66724045d941Ssowmini case DLD_PROP_EN_100FDX_CAP: 66734045d941Ssowmini *(uint8_t *)pr_val = 1; 66744045d941Ssowmini break; 66754045d941Ssowmini default: 66764045d941Ssowmini err = ENOTSUP; 66774045d941Ssowmini break; 66784045d941Ssowmini } 66794045d941Ssowmini return (err); 66804045d941Ssowmini } 6681*6f157acbSml 6682*6f157acbSml 6683*6f157acbSml /* 6684*6f157acbSml * The following is a software around for the Neptune hardware's 6685*6f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 6686*6f157acbSml * an interrupr handler is removed. 6687*6f157acbSml */ 6688*6f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 6689*6f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 6690*6f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 6691*6f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 6692*6f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 6693*6f157acbSml NXGE_GLU_RESET | \ 6694*6f157acbSml NXGE_NIU_RESET) 6695*6f157acbSml 6696*6f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 6697*6f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 6698*6f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 6699*6f157acbSml 6700*6f157acbSml static void 6701*6f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 6702*6f157acbSml { 6703*6f157acbSml uint32_t rvalue; 6704*6f157acbSml p_nxge_hw_list_t hw_p; 6705*6f157acbSml p_nxge_t fnxgep; 6706*6f157acbSml int i, j; 6707*6f157acbSml 6708*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 6709*6f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 6710*6f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6711*6f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 6712*6f157acbSml return; 6713*6f157acbSml } 6714*6f157acbSml 6715*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6716*6f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 6717*6f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 6718*6f157acbSml nxgep->nxge_timerid)); 6719*6f157acbSml 6720*6f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 6721*6f157acbSml /* 6722*6f157acbSml * Make sure other instances from the same hardware 6723*6f157acbSml * stop sending PIO and in quiescent state. 6724*6f157acbSml */ 6725*6f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 6726*6f157acbSml fnxgep = hw_p->nxge_p[i]; 6727*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6728*6f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 6729*6f157acbSml "nxgep $%p", i, fnxgep)); 6730*6f157acbSml #ifdef NXGE_DEBUG 6731*6f157acbSml if (fnxgep) { 6732*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6733*6f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 6734*6f157acbSml "link timer id %d hw timer id %d", 6735*6f157acbSml i, fnxgep->function_num, 6736*6f157acbSml fnxgep->nxge_link_poll_timerid, 6737*6f157acbSml fnxgep->nxge_timerid)); 6738*6f157acbSml } 6739*6f157acbSml #endif 6740*6f157acbSml if (fnxgep && fnxgep != nxgep && 6741*6f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 6742*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6743*6f157acbSml "==> nxge_niu_peu_reset: checking $%p " 6744*6f157acbSml "(function %d) timer ids", 6745*6f157acbSml fnxgep, fnxgep->function_num)); 6746*6f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 6747*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6748*6f157acbSml "==> nxge_niu_peu_reset: waiting")); 6749*6f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 6750*6f157acbSml if (!fnxgep->nxge_timerid && 6751*6f157acbSml !fnxgep->nxge_link_poll_timerid) { 6752*6f157acbSml break; 6753*6f157acbSml } 6754*6f157acbSml } 6755*6f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 6756*6f157acbSml if (fnxgep->nxge_timerid || 6757*6f157acbSml fnxgep->nxge_link_poll_timerid) { 6758*6f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 6759*6f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6760*6f157acbSml "<== nxge_niu_peu_reset: cannot reset " 6761*6f157acbSml "hardware (devices are still in use)")); 6762*6f157acbSml return; 6763*6f157acbSml } 6764*6f157acbSml } 6765*6f157acbSml } 6766*6f157acbSml 6767*6f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 6768*6f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 6769*6f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 6770*6f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 6771*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6772*6f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 6773*6f157acbSml "(data 0x%x)", 6774*6f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 6775*6f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 6776*6f157acbSml rvalue)); 6777*6f157acbSml 6778*6f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 6779*6f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 6780*6f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 6781*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 6782*6f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 6783*6f157acbSml rvalue)); 6784*6f157acbSml 6785*6f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 6786*6f157acbSml } 6787*6f157acbSml 6788*6f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 6789*6f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 6790*6f157acbSml } 6791