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 /* 22a3c5bd6dSspeer * Copyright 2007 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> 3214ea4bb7Ssd #include <sys/pcie.h> 3344961713Sgirish 3444961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3544961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3644961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3744961713Sgirish /* 3844961713Sgirish * until MSIX supported, assume msi, use 2 for msix 3944961713Sgirish */ 4044961713Sgirish uint32_t nxge_msi_enable = 1; /* debug: turn msi off */ 4144961713Sgirish 4244961713Sgirish /* 4344961713Sgirish * Globals: tunable parameters (/etc/system or adb) 4444961713Sgirish * 4544961713Sgirish */ 4644961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 4744961713Sgirish uint32_t nxge_rbr_spare_size = 0; 4844961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 4944961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 5044961713Sgirish uint32_t nxge_no_msg = 0; /* control message display */ 5144961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 5244961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 5344961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 5444961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 5544961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 5644961713Sgirish boolean_t nxge_jumbo_enable = B_FALSE; 5744961713Sgirish uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT; 5844961713Sgirish uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD; 59*1f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 6044961713Sgirish 6144961713Sgirish /* 6244961713Sgirish * Debugging flags: 6344961713Sgirish * nxge_no_tx_lb : transmit load balancing 6444961713Sgirish * nxge_tx_lb_policy: 0 - TCP port (default) 6544961713Sgirish * 3 - DEST MAC 6644961713Sgirish */ 6744961713Sgirish uint32_t nxge_no_tx_lb = 0; 6844961713Sgirish uint32_t nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP; 6944961713Sgirish 7044961713Sgirish /* 7144961713Sgirish * Add tunable to reduce the amount of time spent in the 7244961713Sgirish * ISR doing Rx Processing. 7344961713Sgirish */ 7444961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 7544961713Sgirish 7644961713Sgirish /* 7744961713Sgirish * Tunables to manage the receive buffer blocks. 7844961713Sgirish * 7944961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 8044961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 8144961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 8244961713Sgirish */ 8344961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 8444961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 8544961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 8644961713Sgirish 8744961713Sgirish rtrace_t npi_rtracebuf; 8844961713Sgirish 8944961713Sgirish #if defined(sun4v) 9044961713Sgirish /* 9144961713Sgirish * Hypervisor N2/NIU services information. 9244961713Sgirish */ 9344961713Sgirish static hsvc_info_t niu_hsvc = { 9444961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 9544961713Sgirish NIU_MINOR_VER, "nxge" 9644961713Sgirish }; 9744961713Sgirish #endif 9844961713Sgirish 9944961713Sgirish /* 10044961713Sgirish * Function Prototypes 10144961713Sgirish */ 10244961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 10344961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 10444961713Sgirish static void nxge_unattach(p_nxge_t); 10544961713Sgirish 10644961713Sgirish #if NXGE_PROPERTY 10744961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 10844961713Sgirish #endif 10944961713Sgirish 11044961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 11144961713Sgirish 11244961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 11344961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 11444961713Sgirish 11544961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 11644961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 11744961713Sgirish #ifdef NXGE_DEBUG 11844961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 11944961713Sgirish #endif 12044961713Sgirish 12144961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 12244961713Sgirish static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep); 12344961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 12444961713Sgirish static void nxge_remove_soft_intrs(p_nxge_t nxgep); 12544961713Sgirish 12644961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 12744961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 12844961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 12944961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 13044961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 13144961713Sgirish 13244961713Sgirish static void nxge_suspend(p_nxge_t); 13344961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 13444961713Sgirish 13544961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 13644961713Sgirish static void nxge_destroy_dev(p_nxge_t); 13744961713Sgirish 13844961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 13944961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 14044961713Sgirish 14144961713Sgirish static nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 14244961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 14344961713Sgirish 14444961713Sgirish static nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 14544961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 14644961713Sgirish 14744961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 14844961713Sgirish struct ddi_dma_attr *, 14944961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 15044961713Sgirish p_nxge_dma_common_t); 15144961713Sgirish 15244961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 15344961713Sgirish 15444961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 15544961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 15644961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 15744961713Sgirish 15844961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 15944961713Sgirish p_nxge_dma_common_t *, size_t); 16044961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 16144961713Sgirish 16244961713Sgirish static nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 16344961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 16444961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 16544961713Sgirish 16644961713Sgirish static nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 16744961713Sgirish p_nxge_dma_common_t *, 16844961713Sgirish size_t); 16944961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 17044961713Sgirish 17144961713Sgirish static int nxge_init_common_dev(p_nxge_t); 17244961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 17344961713Sgirish 17444961713Sgirish /* 17544961713Sgirish * The next declarations are for the GLDv3 interface. 17644961713Sgirish */ 17744961713Sgirish static int nxge_m_start(void *); 17844961713Sgirish static void nxge_m_stop(void *); 17944961713Sgirish static int nxge_m_unicst(void *, const uint8_t *); 18044961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 18144961713Sgirish static int nxge_m_promisc(void *, boolean_t); 18244961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 18344961713Sgirish static void nxge_m_resources(void *); 18444961713Sgirish mblk_t *nxge_m_tx(void *arg, mblk_t *); 18544961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t); 18658324dfcSspeer static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 18758324dfcSspeer mac_addr_slot_t slot); 18858324dfcSspeer static void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 18958324dfcSspeer boolean_t factory); 19058324dfcSspeer static int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 19158324dfcSspeer static int nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr); 19258324dfcSspeer static int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 19358324dfcSspeer static int nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 19458324dfcSspeer static int nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 19544961713Sgirish 19644961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 19744961713Sgirish #define MAX_DUMP_SZ 256 19844961713Sgirish 19944961713Sgirish #define NXGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB) 20044961713Sgirish 20144961713Sgirish static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 20244961713Sgirish static mac_callbacks_t nxge_m_callbacks = { 20344961713Sgirish NXGE_M_CALLBACK_FLAGS, 20444961713Sgirish nxge_m_stat, 20544961713Sgirish nxge_m_start, 20644961713Sgirish nxge_m_stop, 20744961713Sgirish nxge_m_promisc, 20844961713Sgirish nxge_m_multicst, 20944961713Sgirish nxge_m_unicst, 21044961713Sgirish nxge_m_tx, 21144961713Sgirish nxge_m_resources, 21244961713Sgirish nxge_m_ioctl, 21344961713Sgirish nxge_m_getcapab 21444961713Sgirish }; 21544961713Sgirish 21644961713Sgirish void 21744961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 21844961713Sgirish 21944961713Sgirish /* 22044961713Sgirish * These global variables control the message 22144961713Sgirish * output. 22244961713Sgirish */ 22344961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 22444961713Sgirish uint64_t nxge_debug_level = 0; 22544961713Sgirish 22644961713Sgirish /* 22744961713Sgirish * This list contains the instance structures for the Neptune 22844961713Sgirish * devices present in the system. The lock exists to guarantee 22944961713Sgirish * mutually exclusive access to the list. 23044961713Sgirish */ 23144961713Sgirish void *nxge_list = NULL; 23244961713Sgirish 23344961713Sgirish void *nxge_hw_list = NULL; 23444961713Sgirish nxge_os_mutex_t nxge_common_lock; 23544961713Sgirish 23644961713Sgirish nxge_os_mutex_t nxge_mii_lock; 23744961713Sgirish static uint32_t nxge_mii_lock_init = 0; 23844961713Sgirish nxge_os_mutex_t nxge_mdio_lock; 23944961713Sgirish static uint32_t nxge_mdio_lock_init = 0; 24044961713Sgirish 24144961713Sgirish extern uint64_t npi_debug_level; 24244961713Sgirish 24344961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 24444961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 24544961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 24644961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 24744961713Sgirish extern void nxge_fm_init(p_nxge_t, 24844961713Sgirish ddi_device_acc_attr_t *, 24944961713Sgirish ddi_device_acc_attr_t *, 25044961713Sgirish ddi_dma_attr_t *); 25144961713Sgirish extern void nxge_fm_fini(p_nxge_t); 25258324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 25344961713Sgirish 25444961713Sgirish /* 25544961713Sgirish * Count used to maintain the number of buffers being used 25644961713Sgirish * by Neptune instances and loaned up to the upper layers. 25744961713Sgirish */ 25844961713Sgirish uint32_t nxge_mblks_pending = 0; 25944961713Sgirish 26044961713Sgirish /* 26144961713Sgirish * Device register access attributes for PIO. 26244961713Sgirish */ 26344961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 26444961713Sgirish DDI_DEVICE_ATTR_V0, 26544961713Sgirish DDI_STRUCTURE_LE_ACC, 26644961713Sgirish DDI_STRICTORDER_ACC, 26744961713Sgirish }; 26844961713Sgirish 26944961713Sgirish /* 27044961713Sgirish * Device descriptor access attributes for DMA. 27144961713Sgirish */ 27244961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 27344961713Sgirish DDI_DEVICE_ATTR_V0, 27444961713Sgirish DDI_STRUCTURE_LE_ACC, 27544961713Sgirish DDI_STRICTORDER_ACC 27644961713Sgirish }; 27744961713Sgirish 27844961713Sgirish /* 27944961713Sgirish * Device buffer access attributes for DMA. 28044961713Sgirish */ 28144961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 28244961713Sgirish DDI_DEVICE_ATTR_V0, 28344961713Sgirish DDI_STRUCTURE_BE_ACC, 28444961713Sgirish DDI_STRICTORDER_ACC 28544961713Sgirish }; 28644961713Sgirish 28744961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 28844961713Sgirish DMA_ATTR_V0, /* version number. */ 28944961713Sgirish 0, /* low address */ 29044961713Sgirish 0xffffffffffffffff, /* high address */ 29144961713Sgirish 0xffffffffffffffff, /* address counter max */ 29244961713Sgirish #ifndef NIU_PA_WORKAROUND 29344961713Sgirish 0x100000, /* alignment */ 29444961713Sgirish #else 29544961713Sgirish 0x2000, 29644961713Sgirish #endif 29744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 29844961713Sgirish 0x1, /* minimum transfer size */ 29944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 30044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 30144961713Sgirish 1, /* scatter/gather list length */ 30244961713Sgirish (unsigned int) 1, /* granularity */ 30344961713Sgirish 0 /* attribute flags */ 30444961713Sgirish }; 30544961713Sgirish 30644961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 30744961713Sgirish DMA_ATTR_V0, /* version number. */ 30844961713Sgirish 0, /* low address */ 30944961713Sgirish 0xffffffffffffffff, /* high address */ 31044961713Sgirish 0xffffffffffffffff, /* address counter max */ 31144961713Sgirish #if defined(_BIG_ENDIAN) 31244961713Sgirish 0x2000, /* alignment */ 31344961713Sgirish #else 31444961713Sgirish 0x1000, /* alignment */ 31544961713Sgirish #endif 31644961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 31744961713Sgirish 0x1, /* minimum transfer size */ 31844961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 31944961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 32044961713Sgirish 5, /* scatter/gather list length */ 32144961713Sgirish (unsigned int) 1, /* granularity */ 32244961713Sgirish 0 /* attribute flags */ 32344961713Sgirish }; 32444961713Sgirish 32544961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 32644961713Sgirish DMA_ATTR_V0, /* version number. */ 32744961713Sgirish 0, /* low address */ 32844961713Sgirish 0xffffffffffffffff, /* high address */ 32944961713Sgirish 0xffffffffffffffff, /* address counter max */ 33044961713Sgirish 0x2000, /* alignment */ 33144961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 33244961713Sgirish 0x1, /* minimum transfer size */ 33344961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 33444961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 33544961713Sgirish 1, /* scatter/gather list length */ 33644961713Sgirish (unsigned int) 1, /* granularity */ 33744961713Sgirish 0 /* attribute flags */ 33844961713Sgirish }; 33944961713Sgirish 34044961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 34144961713Sgirish (uint_t)0, /* dlim_addr_lo */ 34244961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 34344961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 34444961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 34544961713Sgirish 0x1, /* dlim_minxfer */ 34644961713Sgirish 1024 /* dlim_speed */ 34744961713Sgirish }; 34844961713Sgirish 34944961713Sgirish dma_method_t nxge_force_dma = DVMA; 35044961713Sgirish 35144961713Sgirish /* 35244961713Sgirish * dma chunk sizes. 35344961713Sgirish * 35444961713Sgirish * Try to allocate the largest possible size 35544961713Sgirish * so that fewer number of dma chunks would be managed 35644961713Sgirish */ 35744961713Sgirish #ifdef NIU_PA_WORKAROUND 35844961713Sgirish size_t alloc_sizes [] = {0x2000}; 35944961713Sgirish #else 36044961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 36144961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 36244961713Sgirish 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000}; 36344961713Sgirish #endif 36444961713Sgirish 36544961713Sgirish /* 36644961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 36744961713Sgirish */ 36844961713Sgirish 36944961713Sgirish static int 37044961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 37144961713Sgirish { 37244961713Sgirish p_nxge_t nxgep = NULL; 37344961713Sgirish int instance; 37444961713Sgirish int status = DDI_SUCCESS; 37544961713Sgirish nxge_status_t nxge_status = NXGE_OK; 37644961713Sgirish uint8_t portn; 37758324dfcSspeer nxge_mmac_t *mmac_info; 37844961713Sgirish 37944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 38044961713Sgirish 38144961713Sgirish /* 38244961713Sgirish * Get the device instance since we'll need to setup 38344961713Sgirish * or retrieve a soft state for this instance. 38444961713Sgirish */ 38544961713Sgirish instance = ddi_get_instance(dip); 38644961713Sgirish 38744961713Sgirish switch (cmd) { 38844961713Sgirish case DDI_ATTACH: 38944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 39044961713Sgirish break; 39144961713Sgirish 39244961713Sgirish case DDI_RESUME: 39344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 39444961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 39544961713Sgirish if (nxgep == NULL) { 39644961713Sgirish status = DDI_FAILURE; 39744961713Sgirish break; 39844961713Sgirish } 39944961713Sgirish if (nxgep->dip != dip) { 40044961713Sgirish status = DDI_FAILURE; 40144961713Sgirish break; 40244961713Sgirish } 40344961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 40444961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 40544961713Sgirish } else { 40644961713Sgirish nxge_status = nxge_resume(nxgep); 40744961713Sgirish } 40844961713Sgirish goto nxge_attach_exit; 40944961713Sgirish 41044961713Sgirish case DDI_PM_RESUME: 41144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 41244961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 41344961713Sgirish if (nxgep == NULL) { 41444961713Sgirish status = DDI_FAILURE; 41544961713Sgirish break; 41644961713Sgirish } 41744961713Sgirish if (nxgep->dip != dip) { 41844961713Sgirish status = DDI_FAILURE; 41944961713Sgirish break; 42044961713Sgirish } 42144961713Sgirish nxge_status = nxge_resume(nxgep); 42244961713Sgirish goto nxge_attach_exit; 42344961713Sgirish 42444961713Sgirish default: 42544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 42644961713Sgirish status = DDI_FAILURE; 42744961713Sgirish goto nxge_attach_exit; 42844961713Sgirish } 42944961713Sgirish 43044961713Sgirish 43144961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 43244961713Sgirish status = DDI_FAILURE; 43344961713Sgirish goto nxge_attach_exit; 43444961713Sgirish } 43544961713Sgirish 43644961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 43744961713Sgirish if (nxgep == NULL) { 43844961713Sgirish goto nxge_attach_fail; 43944961713Sgirish } 44044961713Sgirish 44144961713Sgirish nxgep->drv_state = 0; 44244961713Sgirish nxgep->dip = dip; 44344961713Sgirish nxgep->instance = instance; 44444961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 44544961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 44644961713Sgirish npi_debug_level = nxge_debug_level; 44744961713Sgirish 44844961713Sgirish nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_dev_desc_dma_acc_attr, 44944961713Sgirish &nxge_rx_dma_attr); 45044961713Sgirish 45144961713Sgirish status = nxge_map_regs(nxgep); 45244961713Sgirish if (status != NXGE_OK) { 45344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 45444961713Sgirish goto nxge_attach_fail; 45544961713Sgirish } 45644961713Sgirish 45744961713Sgirish status = nxge_init_common_dev(nxgep); 45844961713Sgirish if (status != NXGE_OK) { 45944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 46044961713Sgirish "nxge_init_common_dev failed")); 46144961713Sgirish goto nxge_attach_fail; 46244961713Sgirish } 46344961713Sgirish 46444961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 46544961713Sgirish nxgep->mac.portnum = portn; 46644961713Sgirish if ((portn == 0) || (portn == 1)) 46744961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 46844961713Sgirish else 46944961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 47058324dfcSspeer /* 47158324dfcSspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 47258324dfcSspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 47358324dfcSspeer * The two types of MACs have different characterizations. 47458324dfcSspeer */ 47558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 47658324dfcSspeer if (nxgep->function_num < 2) { 47758324dfcSspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 47858324dfcSspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 47958324dfcSspeer } else { 48058324dfcSspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 48158324dfcSspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 48258324dfcSspeer } 48344961713Sgirish /* 48444961713Sgirish * Setup the Ndd parameters for the this instance. 48544961713Sgirish */ 48644961713Sgirish nxge_init_param(nxgep); 48744961713Sgirish 48844961713Sgirish /* 48944961713Sgirish * Setup Register Tracing Buffer. 49044961713Sgirish */ 49144961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 49244961713Sgirish 49344961713Sgirish /* init stats ptr */ 49444961713Sgirish nxge_init_statsp(nxgep); 49544961713Sgirish status = nxge_get_xcvr_type(nxgep); 49644961713Sgirish 49744961713Sgirish if (status != NXGE_OK) { 498a3c5bd6dSspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_attach: " 49944961713Sgirish " Couldn't determine card type" 50044961713Sgirish " .... exit ")); 50144961713Sgirish goto nxge_attach_fail; 50244961713Sgirish } 50344961713Sgirish 50444961713Sgirish if ((nxgep->niu_type == NEPTUNE) && 50544961713Sgirish (nxgep->mac.portmode == PORT_10G_FIBER)) { 50644961713Sgirish nxgep->niu_type = NEPTUNE_2; 50744961713Sgirish } 50844961713Sgirish 50944961713Sgirish status = nxge_get_config_properties(nxgep); 51044961713Sgirish 51144961713Sgirish if (status != NXGE_OK) { 51244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "get_hw create failed")); 51344961713Sgirish goto nxge_attach_fail; 51444961713Sgirish } 51544961713Sgirish 51644961713Sgirish nxge_get_xcvr_properties(nxgep); 51744961713Sgirish 51844961713Sgirish /* 51944961713Sgirish * Setup the Kstats for the driver. 52044961713Sgirish */ 52144961713Sgirish nxge_setup_kstats(nxgep); 52244961713Sgirish 52344961713Sgirish nxge_setup_param(nxgep); 52444961713Sgirish 52544961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 52644961713Sgirish if (status != NXGE_OK) { 52744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 52844961713Sgirish goto nxge_attach_fail; 52944961713Sgirish } 53044961713Sgirish 53144961713Sgirish #if defined(sun4v) 53244961713Sgirish if (nxgep->niu_type == N2_NIU) { 53344961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 53444961713Sgirish bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 53544961713Sgirish if ((status = 53644961713Sgirish hsvc_register(&nxgep->niu_hsvc, 53744961713Sgirish &nxgep->niu_min_ver)) != 0) { 53844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 53944961713Sgirish "nxge_attach: " 54044961713Sgirish "%s: cannot negotiate " 54144961713Sgirish "hypervisor services " 54244961713Sgirish "revision %d " 54344961713Sgirish "group: 0x%lx " 54444961713Sgirish "major: 0x%lx minor: 0x%lx " 54544961713Sgirish "errno: %d", 54644961713Sgirish niu_hsvc.hsvc_modname, 54744961713Sgirish niu_hsvc.hsvc_rev, 54844961713Sgirish niu_hsvc.hsvc_group, 54944961713Sgirish niu_hsvc.hsvc_major, 55044961713Sgirish niu_hsvc.hsvc_minor, 55144961713Sgirish status)); 55244961713Sgirish status = DDI_FAILURE; 55344961713Sgirish goto nxge_attach_fail; 55444961713Sgirish } 55544961713Sgirish 55644961713Sgirish nxgep->niu_hsvc_available = B_TRUE; 55744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 55844961713Sgirish "NIU Hypervisor service enabled")); 55944961713Sgirish } 56044961713Sgirish #endif 56144961713Sgirish 56244961713Sgirish nxge_hw_id_init(nxgep); 56344961713Sgirish nxge_hw_init_niu_common(nxgep); 56444961713Sgirish 56544961713Sgirish status = nxge_setup_mutexes(nxgep); 56644961713Sgirish if (status != NXGE_OK) { 56744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 56844961713Sgirish goto nxge_attach_fail; 56944961713Sgirish } 57044961713Sgirish 57144961713Sgirish status = nxge_setup_dev(nxgep); 57244961713Sgirish if (status != DDI_SUCCESS) { 57344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 57444961713Sgirish goto nxge_attach_fail; 57544961713Sgirish } 57644961713Sgirish 57744961713Sgirish status = nxge_add_intrs(nxgep); 57844961713Sgirish if (status != DDI_SUCCESS) { 57944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 58044961713Sgirish goto nxge_attach_fail; 58144961713Sgirish } 58244961713Sgirish status = nxge_add_soft_intrs(nxgep); 58344961713Sgirish if (status != DDI_SUCCESS) { 58444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "add_soft_intr failed")); 58544961713Sgirish goto nxge_attach_fail; 58644961713Sgirish } 58744961713Sgirish 58844961713Sgirish /* 58944961713Sgirish * Enable interrupts. 59044961713Sgirish */ 59144961713Sgirish nxge_intrs_enable(nxgep); 59244961713Sgirish 59344961713Sgirish if ((status = nxge_mac_register(nxgep)) != DDI_SUCCESS) { 59444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 59544961713Sgirish "unable to register to mac layer (%d)", status)); 59644961713Sgirish goto nxge_attach_fail; 59744961713Sgirish } 59844961713Sgirish 59944961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 60044961713Sgirish 60144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "registered to mac (instance %d)", 60244961713Sgirish instance)); 60344961713Sgirish 60444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 60544961713Sgirish 60644961713Sgirish goto nxge_attach_exit; 60744961713Sgirish 60844961713Sgirish nxge_attach_fail: 60944961713Sgirish nxge_unattach(nxgep); 61044961713Sgirish if (nxge_status != NXGE_OK) 61144961713Sgirish nxge_status = (NXGE_ERROR | NXGE_DDI_FAILED); 61244961713Sgirish nxgep = NULL; 61344961713Sgirish 61444961713Sgirish nxge_attach_exit: 61544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 61644961713Sgirish status)); 61744961713Sgirish 61844961713Sgirish return (status); 61944961713Sgirish } 62044961713Sgirish 62144961713Sgirish static int 62244961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 62344961713Sgirish { 62444961713Sgirish int status = DDI_SUCCESS; 62544961713Sgirish int instance; 62644961713Sgirish p_nxge_t nxgep = NULL; 62744961713Sgirish 62844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 62944961713Sgirish instance = ddi_get_instance(dip); 63044961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 63144961713Sgirish if (nxgep == NULL) { 63244961713Sgirish status = DDI_FAILURE; 63344961713Sgirish goto nxge_detach_exit; 63444961713Sgirish } 63544961713Sgirish 63644961713Sgirish switch (cmd) { 63744961713Sgirish case DDI_DETACH: 63844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 63944961713Sgirish break; 64044961713Sgirish 64144961713Sgirish case DDI_PM_SUSPEND: 64244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 64344961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 64444961713Sgirish nxge_suspend(nxgep); 64544961713Sgirish break; 64644961713Sgirish 64744961713Sgirish case DDI_SUSPEND: 64844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 64944961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 65044961713Sgirish nxgep->suspended = DDI_SUSPEND; 65144961713Sgirish nxge_suspend(nxgep); 65244961713Sgirish } 65344961713Sgirish break; 65444961713Sgirish 65544961713Sgirish default: 65644961713Sgirish status = DDI_FAILURE; 65744961713Sgirish } 65844961713Sgirish 65944961713Sgirish if (cmd != DDI_DETACH) 66044961713Sgirish goto nxge_detach_exit; 66144961713Sgirish 66244961713Sgirish /* 66344961713Sgirish * Stop the xcvr polling. 66444961713Sgirish */ 66544961713Sgirish nxgep->suspended = cmd; 66644961713Sgirish 66744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 66844961713Sgirish 66944961713Sgirish if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 67044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 67144961713Sgirish "<== nxge_detach status = 0x%08X", status)); 67244961713Sgirish return (DDI_FAILURE); 67344961713Sgirish } 67444961713Sgirish 67544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 67644961713Sgirish "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 67744961713Sgirish 67844961713Sgirish nxge_unattach(nxgep); 67944961713Sgirish nxgep = NULL; 68044961713Sgirish 68144961713Sgirish nxge_detach_exit: 68244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 68344961713Sgirish status)); 68444961713Sgirish 68544961713Sgirish return (status); 68644961713Sgirish } 68744961713Sgirish 68844961713Sgirish static void 68944961713Sgirish nxge_unattach(p_nxge_t nxgep) 69044961713Sgirish { 69144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 69244961713Sgirish 69344961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 69444961713Sgirish return; 69544961713Sgirish } 69644961713Sgirish 69744961713Sgirish if (nxgep->nxge_hw_p) { 69844961713Sgirish nxge_uninit_common_dev(nxgep); 69944961713Sgirish nxgep->nxge_hw_p = NULL; 70044961713Sgirish } 70144961713Sgirish 70244961713Sgirish if (nxgep->nxge_timerid) { 70344961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 70444961713Sgirish nxgep->nxge_timerid = 0; 70544961713Sgirish } 70644961713Sgirish 70744961713Sgirish #if defined(sun4v) 70844961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 70944961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 71044961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 71144961713Sgirish } 71244961713Sgirish #endif 71344961713Sgirish /* 71444961713Sgirish * Stop any further interrupts. 71544961713Sgirish */ 71644961713Sgirish nxge_remove_intrs(nxgep); 71744961713Sgirish 71844961713Sgirish /* remove soft interrups */ 71944961713Sgirish nxge_remove_soft_intrs(nxgep); 72044961713Sgirish 72144961713Sgirish /* 72244961713Sgirish * Stop the device and free resources. 72344961713Sgirish */ 72444961713Sgirish nxge_destroy_dev(nxgep); 72544961713Sgirish 72644961713Sgirish /* 72744961713Sgirish * Tear down the ndd parameters setup. 72844961713Sgirish */ 72944961713Sgirish nxge_destroy_param(nxgep); 73044961713Sgirish 73144961713Sgirish /* 73244961713Sgirish * Tear down the kstat setup. 73344961713Sgirish */ 73444961713Sgirish nxge_destroy_kstats(nxgep); 73544961713Sgirish 73644961713Sgirish /* 73744961713Sgirish * Destroy all mutexes. 73844961713Sgirish */ 73944961713Sgirish nxge_destroy_mutexes(nxgep); 74044961713Sgirish 74144961713Sgirish /* 74244961713Sgirish * Remove the list of ndd parameters which 74344961713Sgirish * were setup during attach. 74444961713Sgirish */ 74544961713Sgirish if (nxgep->dip) { 74644961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 74744961713Sgirish " nxge_unattach: remove all properties")); 74844961713Sgirish 74944961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 75044961713Sgirish } 75144961713Sgirish 75244961713Sgirish #if NXGE_PROPERTY 75344961713Sgirish nxge_remove_hard_properties(nxgep); 75444961713Sgirish #endif 75544961713Sgirish 75644961713Sgirish /* 75744961713Sgirish * Unmap the register setup. 75844961713Sgirish */ 75944961713Sgirish nxge_unmap_regs(nxgep); 76044961713Sgirish 76144961713Sgirish nxge_fm_fini(nxgep); 76244961713Sgirish 76344961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 76444961713Sgirish 76544961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 76644961713Sgirish } 76744961713Sgirish 76844961713Sgirish static char n2_siu_name[] = "niu"; 76944961713Sgirish 77044961713Sgirish static nxge_status_t 77144961713Sgirish nxge_map_regs(p_nxge_t nxgep) 77244961713Sgirish { 77344961713Sgirish int ddi_status = DDI_SUCCESS; 77444961713Sgirish p_dev_regs_t dev_regs; 77544961713Sgirish char buf[MAXPATHLEN + 1]; 77644961713Sgirish char *devname; 77744961713Sgirish #ifdef NXGE_DEBUG 77844961713Sgirish char *sysname; 77944961713Sgirish #endif 78044961713Sgirish off_t regsize; 78144961713Sgirish nxge_status_t status = NXGE_OK; 78214ea4bb7Ssd #if !defined(_BIG_ENDIAN) 78314ea4bb7Ssd off_t pci_offset; 78414ea4bb7Ssd uint16_t pcie_devctl; 78514ea4bb7Ssd #endif 78644961713Sgirish 78744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 78844961713Sgirish nxgep->dev_regs = NULL; 78944961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 79044961713Sgirish dev_regs->nxge_regh = NULL; 79144961713Sgirish dev_regs->nxge_pciregh = NULL; 79244961713Sgirish dev_regs->nxge_msix_regh = NULL; 79344961713Sgirish dev_regs->nxge_vir_regh = NULL; 79444961713Sgirish dev_regs->nxge_vir2_regh = NULL; 79544961713Sgirish nxgep->niu_type = NEPTUNE; 79644961713Sgirish 79744961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 79844961713Sgirish ASSERT(strlen(devname) > 0); 79944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 80044961713Sgirish "nxge_map_regs: pathname devname %s", devname)); 80144961713Sgirish 80244961713Sgirish if (strstr(devname, n2_siu_name)) { 80344961713Sgirish /* N2/NIU */ 80444961713Sgirish nxgep->niu_type = N2_NIU; 80544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 80644961713Sgirish "nxge_map_regs: N2/NIU devname %s", devname)); 80744961713Sgirish /* get function number */ 80844961713Sgirish nxgep->function_num = 80944961713Sgirish (devname[strlen(devname) -1] == '1' ? 1 : 0); 81044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 81144961713Sgirish "nxge_map_regs: N2/NIU function number %d", 81244961713Sgirish nxgep->function_num)); 81344961713Sgirish } else { 81444961713Sgirish int *prop_val; 81544961713Sgirish uint_t prop_len; 81644961713Sgirish uint8_t func_num; 81744961713Sgirish 81844961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 81944961713Sgirish 0, "reg", 82044961713Sgirish &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 82144961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 82244961713Sgirish "Reg property not found")); 82344961713Sgirish ddi_status = DDI_FAILURE; 82444961713Sgirish goto nxge_map_regs_fail0; 82544961713Sgirish 82644961713Sgirish } else { 82744961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 82844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 82944961713Sgirish "Reg property found: fun # %d", 83044961713Sgirish func_num)); 83144961713Sgirish nxgep->function_num = func_num; 83244961713Sgirish ddi_prop_free(prop_val); 83344961713Sgirish } 83444961713Sgirish } 83544961713Sgirish 83644961713Sgirish switch (nxgep->niu_type) { 83744961713Sgirish case NEPTUNE: 83844961713Sgirish case NEPTUNE_2: 83944961713Sgirish default: 84044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 84144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 84244961713Sgirish "nxge_map_regs: pci config size 0x%x", regsize)); 84344961713Sgirish 84444961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 84544961713Sgirish (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 84644961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 84744961713Sgirish if (ddi_status != DDI_SUCCESS) { 84844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 84944961713Sgirish "ddi_map_regs, nxge bus config regs failed")); 85044961713Sgirish goto nxge_map_regs_fail0; 85144961713Sgirish } 85244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 85344961713Sgirish "nxge_map_reg: PCI config addr 0x%0llx " 85444961713Sgirish " handle 0x%0llx", dev_regs->nxge_pciregp, 85544961713Sgirish dev_regs->nxge_pciregh)); 85644961713Sgirish /* 85744961713Sgirish * IMP IMP 85844961713Sgirish * workaround for bit swapping bug in HW 85944961713Sgirish * which ends up in no-snoop = yes 86044961713Sgirish * resulting, in DMA not synched properly 86144961713Sgirish */ 86244961713Sgirish #if !defined(_BIG_ENDIAN) 86314ea4bb7Ssd /* workarounds for x86 systems */ 86414ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 86514ea4bb7Ssd pcie_devctl = 0x0; 86614ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 86714ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 86814ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 86914ea4bb7Ssd pcie_devctl); 87044961713Sgirish #endif 87114ea4bb7Ssd 87244961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 87344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 87444961713Sgirish "nxge_map_regs: pio size 0x%x", regsize)); 87544961713Sgirish /* set up the device mapped register */ 87644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 87744961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 87844961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 87944961713Sgirish if (ddi_status != DDI_SUCCESS) { 88044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 88144961713Sgirish "ddi_map_regs for Neptune global reg failed")); 88244961713Sgirish goto nxge_map_regs_fail1; 88344961713Sgirish } 88444961713Sgirish 88544961713Sgirish /* set up the msi/msi-x mapped register */ 88644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 88744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 88844961713Sgirish "nxge_map_regs: msix size 0x%x", regsize)); 88944961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 89044961713Sgirish (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 89144961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 89244961713Sgirish if (ddi_status != DDI_SUCCESS) { 89344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 89444961713Sgirish "ddi_map_regs for msi reg failed")); 89544961713Sgirish goto nxge_map_regs_fail2; 89644961713Sgirish } 89744961713Sgirish 89844961713Sgirish /* set up the vio region mapped register */ 89944961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 90044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 90144961713Sgirish "nxge_map_regs: vio size 0x%x", regsize)); 90244961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 90344961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 90444961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 90544961713Sgirish 90644961713Sgirish if (ddi_status != DDI_SUCCESS) { 90744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 90844961713Sgirish "ddi_map_regs for nxge vio reg failed")); 90944961713Sgirish goto nxge_map_regs_fail3; 91044961713Sgirish } 91144961713Sgirish nxgep->dev_regs = dev_regs; 91244961713Sgirish 91344961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 91444961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 91544961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_pciregp); 91644961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 91744961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 91844961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 91944961713Sgirish 92044961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 92144961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 92244961713Sgirish 92344961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 92444961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 92544961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 92644961713Sgirish 92744961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 92844961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 92944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 93044961713Sgirish 93144961713Sgirish break; 93244961713Sgirish 93344961713Sgirish case N2_NIU: 93444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 93544961713Sgirish /* 93644961713Sgirish * Set up the device mapped register (FWARC 2006/556) 93744961713Sgirish * (changed back to 1: reg starts at 1!) 93844961713Sgirish */ 93944961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 94044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 94144961713Sgirish "nxge_map_regs: dev size 0x%x", regsize)); 94244961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 94344961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 94444961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 94544961713Sgirish 94644961713Sgirish if (ddi_status != DDI_SUCCESS) { 94744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 94844961713Sgirish "ddi_map_regs for N2/NIU, global reg failed ")); 94944961713Sgirish goto nxge_map_regs_fail1; 95044961713Sgirish } 95144961713Sgirish 95244961713Sgirish /* set up the vio region mapped register */ 95344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 95444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 95544961713Sgirish "nxge_map_regs: vio (1) size 0x%x", regsize)); 95644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 95744961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 95844961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 95944961713Sgirish 96044961713Sgirish if (ddi_status != DDI_SUCCESS) { 96144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 96244961713Sgirish "ddi_map_regs for nxge vio reg failed")); 96344961713Sgirish goto nxge_map_regs_fail2; 96444961713Sgirish } 96544961713Sgirish /* set up the vio region mapped register */ 96644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 96744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 96844961713Sgirish "nxge_map_regs: vio (3) size 0x%x", regsize)); 96944961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 97044961713Sgirish (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 97144961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 97244961713Sgirish 97344961713Sgirish if (ddi_status != DDI_SUCCESS) { 97444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 97544961713Sgirish "ddi_map_regs for nxge vio2 reg failed")); 97644961713Sgirish goto nxge_map_regs_fail3; 97744961713Sgirish } 97844961713Sgirish nxgep->dev_regs = dev_regs; 97944961713Sgirish 98044961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 98144961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 98244961713Sgirish 98344961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 98444961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 98544961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 98644961713Sgirish 98744961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 98844961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 98944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 99044961713Sgirish 99144961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 99244961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 99344961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 99444961713Sgirish 99544961713Sgirish break; 99644961713Sgirish } 99744961713Sgirish 99844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 99944961713Sgirish " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 100044961713Sgirish 100144961713Sgirish goto nxge_map_regs_exit; 100244961713Sgirish nxge_map_regs_fail3: 100344961713Sgirish if (dev_regs->nxge_msix_regh) { 100444961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 100544961713Sgirish } 100644961713Sgirish if (dev_regs->nxge_vir_regh) { 100744961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 100844961713Sgirish } 100944961713Sgirish nxge_map_regs_fail2: 101044961713Sgirish if (dev_regs->nxge_regh) { 101144961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 101244961713Sgirish } 101344961713Sgirish nxge_map_regs_fail1: 101444961713Sgirish if (dev_regs->nxge_pciregh) { 101544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 101644961713Sgirish } 101744961713Sgirish nxge_map_regs_fail0: 101844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 101944961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 102044961713Sgirish 102144961713Sgirish nxge_map_regs_exit: 102244961713Sgirish if (ddi_status != DDI_SUCCESS) 102344961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 102444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 102544961713Sgirish return (status); 102644961713Sgirish } 102744961713Sgirish 102844961713Sgirish static void 102944961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 103044961713Sgirish { 103144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 103244961713Sgirish if (nxgep->dev_regs) { 103344961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 103444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 103544961713Sgirish "==> nxge_unmap_regs: bus")); 103644961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 103744961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 103844961713Sgirish } 103944961713Sgirish if (nxgep->dev_regs->nxge_regh) { 104044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 104144961713Sgirish "==> nxge_unmap_regs: device registers")); 104244961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 104344961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 104444961713Sgirish } 104544961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 104644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 104744961713Sgirish "==> nxge_unmap_regs: device interrupts")); 104844961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 104944961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 105044961713Sgirish } 105144961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 105244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 105344961713Sgirish "==> nxge_unmap_regs: vio region")); 105444961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 105544961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 105644961713Sgirish } 105744961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 105844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 105944961713Sgirish "==> nxge_unmap_regs: vio2 region")); 106044961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 106144961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 106244961713Sgirish } 106344961713Sgirish 106444961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 106544961713Sgirish nxgep->dev_regs = NULL; 106644961713Sgirish } 106744961713Sgirish 106844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 106944961713Sgirish } 107044961713Sgirish 107144961713Sgirish static nxge_status_t 107244961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 107344961713Sgirish { 107444961713Sgirish int ddi_status = DDI_SUCCESS; 107544961713Sgirish nxge_status_t status = NXGE_OK; 107644961713Sgirish nxge_classify_t *classify_ptr; 107744961713Sgirish int partition; 107844961713Sgirish 107944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 108044961713Sgirish 108144961713Sgirish /* 108244961713Sgirish * Get the interrupt cookie so the mutexes can be 108358324dfcSspeer * Initialized. 108444961713Sgirish */ 108544961713Sgirish ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 108644961713Sgirish &nxgep->interrupt_cookie); 108744961713Sgirish if (ddi_status != DDI_SUCCESS) { 108844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 108944961713Sgirish "<== nxge_setup_mutexes: failed 0x%x", ddi_status)); 109044961713Sgirish goto nxge_setup_mutexes_exit; 109144961713Sgirish } 109244961713Sgirish 109344961713Sgirish /* Initialize global mutex */ 109444961713Sgirish 109544961713Sgirish if (nxge_mdio_lock_init == 0) { 109644961713Sgirish MUTEX_INIT(&nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 109744961713Sgirish } 109844961713Sgirish atomic_add_32(&nxge_mdio_lock_init, 1); 109944961713Sgirish 110044961713Sgirish if (nxge_mii_lock_init == 0) { 110144961713Sgirish MUTEX_INIT(&nxge_mii_lock, NULL, MUTEX_DRIVER, NULL); 110244961713Sgirish } 110344961713Sgirish atomic_add_32(&nxge_mii_lock_init, 1); 110444961713Sgirish 110544961713Sgirish nxgep->drv_state |= STATE_MDIO_LOCK_INIT; 110644961713Sgirish nxgep->drv_state |= STATE_MII_LOCK_INIT; 110744961713Sgirish 110844961713Sgirish /* 110944961713Sgirish * Initialize mutex's for this device. 111044961713Sgirish */ 111144961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 111244961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 111344961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 111444961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 111544961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 111644961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 111744961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 111844961713Sgirish RW_DRIVER, (void *)nxgep->interrupt_cookie); 111944961713Sgirish 112044961713Sgirish classify_ptr = &nxgep->classifier; 112144961713Sgirish /* 112244961713Sgirish * FFLP Mutexes are never used in interrupt context 112344961713Sgirish * as fflp operation can take very long time to 112444961713Sgirish * complete and hence not suitable to invoke from interrupt 112544961713Sgirish * handlers. 112644961713Sgirish */ 112744961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 112844961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 112944961713Sgirish if (nxgep->niu_type == NEPTUNE) { 113044961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 113144961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 113244961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 113344961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 113444961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 113544961713Sgirish } 113644961713Sgirish } 113744961713Sgirish 113844961713Sgirish nxge_setup_mutexes_exit: 113944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 114044961713Sgirish "<== nxge_setup_mutexes status = %x", status)); 114144961713Sgirish 114244961713Sgirish if (ddi_status != DDI_SUCCESS) 114344961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 114444961713Sgirish 114544961713Sgirish return (status); 114644961713Sgirish } 114744961713Sgirish 114844961713Sgirish static void 114944961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 115044961713Sgirish { 115144961713Sgirish int partition; 115244961713Sgirish nxge_classify_t *classify_ptr; 115344961713Sgirish 115444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 115544961713Sgirish RW_DESTROY(&nxgep->filter_lock); 115644961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 115744961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 115844961713Sgirish MUTEX_DESTROY(nxgep->genlock); 115944961713Sgirish 116044961713Sgirish classify_ptr = &nxgep->classifier; 116144961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 116244961713Sgirish 116344961713Sgirish /* free data structures, based on HW type */ 116444961713Sgirish if (nxgep->niu_type == NEPTUNE) { 116544961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 116644961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 116744961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 116844961713Sgirish } 116944961713Sgirish } 117044961713Sgirish if (nxgep->drv_state & STATE_MDIO_LOCK_INIT) { 117144961713Sgirish if (nxge_mdio_lock_init == 1) { 117244961713Sgirish MUTEX_DESTROY(&nxge_mdio_lock); 117344961713Sgirish } 117444961713Sgirish atomic_add_32(&nxge_mdio_lock_init, -1); 117544961713Sgirish } 117644961713Sgirish if (nxgep->drv_state & STATE_MII_LOCK_INIT) { 117744961713Sgirish if (nxge_mii_lock_init == 1) { 117844961713Sgirish MUTEX_DESTROY(&nxge_mii_lock); 117944961713Sgirish } 118044961713Sgirish atomic_add_32(&nxge_mii_lock_init, -1); 118144961713Sgirish } 118244961713Sgirish 118344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 118444961713Sgirish } 118544961713Sgirish 118644961713Sgirish nxge_status_t 118744961713Sgirish nxge_init(p_nxge_t nxgep) 118844961713Sgirish { 118944961713Sgirish nxge_status_t status = NXGE_OK; 119044961713Sgirish 119144961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 119244961713Sgirish 119314ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 119414ea4bb7Ssd return (status); 119514ea4bb7Ssd } 119614ea4bb7Ssd 119744961713Sgirish /* 119844961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 119944961713Sgirish * and receive/transmit descriptor rings. 120044961713Sgirish */ 120144961713Sgirish status = nxge_alloc_mem_pool(nxgep); 120244961713Sgirish if (status != NXGE_OK) { 120344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 120444961713Sgirish goto nxge_init_fail1; 120544961713Sgirish } 120644961713Sgirish 120744961713Sgirish /* 120844961713Sgirish * Initialize and enable TXC registers 120944961713Sgirish * (Globally enable TX controller, 121044961713Sgirish * enable a port, configure dma channel bitmap, 121144961713Sgirish * configure the max burst size). 121244961713Sgirish */ 121344961713Sgirish status = nxge_txc_init(nxgep); 121444961713Sgirish if (status != NXGE_OK) { 121544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txc failed\n")); 121644961713Sgirish goto nxge_init_fail2; 121744961713Sgirish } 121844961713Sgirish 121944961713Sgirish /* 122044961713Sgirish * Initialize and enable TXDMA channels. 122144961713Sgirish */ 122244961713Sgirish status = nxge_init_txdma_channels(nxgep); 122344961713Sgirish if (status != NXGE_OK) { 122444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 122544961713Sgirish goto nxge_init_fail3; 122644961713Sgirish } 122744961713Sgirish 122844961713Sgirish /* 122944961713Sgirish * Initialize and enable RXDMA channels. 123044961713Sgirish */ 123144961713Sgirish status = nxge_init_rxdma_channels(nxgep); 123244961713Sgirish if (status != NXGE_OK) { 123344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 123444961713Sgirish goto nxge_init_fail4; 123544961713Sgirish } 123644961713Sgirish 123744961713Sgirish /* 123844961713Sgirish * Initialize TCAM and FCRAM (Neptune). 123944961713Sgirish */ 124044961713Sgirish status = nxge_classify_init(nxgep); 124144961713Sgirish if (status != NXGE_OK) { 124244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 124344961713Sgirish goto nxge_init_fail5; 124444961713Sgirish } 124544961713Sgirish 124644961713Sgirish /* 124744961713Sgirish * Initialize ZCP 124844961713Sgirish */ 124944961713Sgirish status = nxge_zcp_init(nxgep); 125044961713Sgirish if (status != NXGE_OK) { 125144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 125244961713Sgirish goto nxge_init_fail5; 125344961713Sgirish } 125444961713Sgirish 125544961713Sgirish /* 125644961713Sgirish * Initialize IPP. 125744961713Sgirish */ 125844961713Sgirish status = nxge_ipp_init(nxgep); 125944961713Sgirish if (status != NXGE_OK) { 126044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 126144961713Sgirish goto nxge_init_fail5; 126244961713Sgirish } 126344961713Sgirish 126444961713Sgirish /* 126544961713Sgirish * Initialize the MAC block. 126644961713Sgirish */ 126744961713Sgirish status = nxge_mac_init(nxgep); 126844961713Sgirish if (status != NXGE_OK) { 126944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 127044961713Sgirish goto nxge_init_fail5; 127144961713Sgirish } 127244961713Sgirish 127344961713Sgirish nxge_intrs_enable(nxgep); 127444961713Sgirish 127544961713Sgirish /* 127644961713Sgirish * Enable hardware interrupts. 127744961713Sgirish */ 127844961713Sgirish nxge_intr_hw_enable(nxgep); 127944961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 128044961713Sgirish 128144961713Sgirish goto nxge_init_exit; 128244961713Sgirish 128344961713Sgirish nxge_init_fail5: 128444961713Sgirish nxge_uninit_rxdma_channels(nxgep); 128544961713Sgirish nxge_init_fail4: 128644961713Sgirish nxge_uninit_txdma_channels(nxgep); 128744961713Sgirish nxge_init_fail3: 128844961713Sgirish (void) nxge_txc_uninit(nxgep); 128944961713Sgirish nxge_init_fail2: 129044961713Sgirish nxge_free_mem_pool(nxgep); 129144961713Sgirish nxge_init_fail1: 129244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 129344961713Sgirish "<== nxge_init status (failed) = 0x%08x", status)); 129444961713Sgirish return (status); 129544961713Sgirish 129644961713Sgirish nxge_init_exit: 129744961713Sgirish 129844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 129944961713Sgirish status)); 130044961713Sgirish return (status); 130144961713Sgirish } 130244961713Sgirish 130344961713Sgirish 130444961713Sgirish timeout_id_t 130544961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 130644961713Sgirish { 130744961713Sgirish if ((nxgep->suspended == 0) || 130844961713Sgirish (nxgep->suspended == DDI_RESUME)) { 130944961713Sgirish return (timeout(func, (caddr_t)nxgep, 131044961713Sgirish drv_usectohz(1000 * msec))); 131144961713Sgirish } 131244961713Sgirish return (NULL); 131344961713Sgirish } 131444961713Sgirish 131544961713Sgirish /*ARGSUSED*/ 131644961713Sgirish void 131744961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 131844961713Sgirish { 131944961713Sgirish if (timerid) { 132044961713Sgirish (void) untimeout(timerid); 132144961713Sgirish } 132244961713Sgirish } 132344961713Sgirish 132444961713Sgirish void 132544961713Sgirish nxge_uninit(p_nxge_t nxgep) 132644961713Sgirish { 132744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 132844961713Sgirish 132944961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 133044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 133144961713Sgirish "==> nxge_uninit: not initialized")); 133244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 133344961713Sgirish "<== nxge_uninit")); 133444961713Sgirish return; 133544961713Sgirish } 133644961713Sgirish 133744961713Sgirish /* stop timer */ 133844961713Sgirish if (nxgep->nxge_timerid) { 133944961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 134044961713Sgirish nxgep->nxge_timerid = 0; 134144961713Sgirish } 134244961713Sgirish 134344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 134444961713Sgirish (void) nxge_intr_hw_disable(nxgep); 134544961713Sgirish 134644961713Sgirish /* 134744961713Sgirish * Reset the receive MAC side. 134844961713Sgirish */ 134944961713Sgirish (void) nxge_rx_mac_disable(nxgep); 135044961713Sgirish 135144961713Sgirish /* Disable and soft reset the IPP */ 135244961713Sgirish (void) nxge_ipp_disable(nxgep); 135344961713Sgirish 1354a3c5bd6dSspeer /* Free classification resources */ 1355a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1356a3c5bd6dSspeer 135744961713Sgirish /* 135844961713Sgirish * Reset the transmit/receive DMA side. 135944961713Sgirish */ 136044961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 136144961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 136244961713Sgirish 136344961713Sgirish nxge_uninit_txdma_channels(nxgep); 136444961713Sgirish nxge_uninit_rxdma_channels(nxgep); 136544961713Sgirish 136644961713Sgirish /* 136744961713Sgirish * Reset the transmit MAC side. 136844961713Sgirish */ 136944961713Sgirish (void) nxge_tx_mac_disable(nxgep); 137044961713Sgirish 137144961713Sgirish nxge_free_mem_pool(nxgep); 137244961713Sgirish 137344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 137444961713Sgirish 137544961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 137644961713Sgirish 137744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 137844961713Sgirish "nxge_mblks_pending %d", nxge_mblks_pending)); 137944961713Sgirish } 138044961713Sgirish 138144961713Sgirish void 138244961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 138344961713Sgirish { 138444961713Sgirish uint64_t reg; 138544961713Sgirish uint64_t regdata; 138644961713Sgirish int i, retry; 138744961713Sgirish 138844961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 138944961713Sgirish regdata = 0; 139044961713Sgirish retry = 1; 139144961713Sgirish 139244961713Sgirish for (i = 0; i < retry; i++) { 139344961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 139444961713Sgirish } 139544961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 139644961713Sgirish } 139744961713Sgirish 139844961713Sgirish void 139944961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 140044961713Sgirish { 140144961713Sgirish uint64_t reg; 140244961713Sgirish uint64_t buf[2]; 140344961713Sgirish 140444961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 140544961713Sgirish reg = buf[0]; 140644961713Sgirish 140744961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 140844961713Sgirish } 140944961713Sgirish 141044961713Sgirish 141144961713Sgirish nxge_os_mutex_t nxgedebuglock; 141244961713Sgirish int nxge_debug_init = 0; 141344961713Sgirish 141444961713Sgirish /*ARGSUSED*/ 141544961713Sgirish /*VARARGS*/ 141644961713Sgirish void 141744961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 141844961713Sgirish { 141944961713Sgirish char msg_buffer[1048]; 142044961713Sgirish char prefix_buffer[32]; 142144961713Sgirish int instance; 142244961713Sgirish uint64_t debug_level; 142344961713Sgirish int cmn_level = CE_CONT; 142444961713Sgirish va_list ap; 142544961713Sgirish 142644961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 142744961713Sgirish nxgep->nxge_debug_level; 142844961713Sgirish 142944961713Sgirish if ((level & debug_level) || 143044961713Sgirish (level == NXGE_NOTE) || 143144961713Sgirish (level == NXGE_ERR_CTL)) { 143244961713Sgirish /* do the msg processing */ 143344961713Sgirish if (nxge_debug_init == 0) { 143444961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 143544961713Sgirish nxge_debug_init = 1; 143644961713Sgirish } 143744961713Sgirish 143844961713Sgirish MUTEX_ENTER(&nxgedebuglock); 143944961713Sgirish 144044961713Sgirish if ((level & NXGE_NOTE)) { 144144961713Sgirish cmn_level = CE_NOTE; 144244961713Sgirish } 144344961713Sgirish 144444961713Sgirish if (level & NXGE_ERR_CTL) { 144544961713Sgirish cmn_level = CE_WARN; 144644961713Sgirish } 144744961713Sgirish 144844961713Sgirish va_start(ap, fmt); 144944961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 145044961713Sgirish va_end(ap); 145144961713Sgirish if (nxgep == NULL) { 145244961713Sgirish instance = -1; 145344961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 145444961713Sgirish } else { 145544961713Sgirish instance = nxgep->instance; 145644961713Sgirish (void) sprintf(prefix_buffer, 145744961713Sgirish "%s%d :", "nxge", instance); 145844961713Sgirish } 145944961713Sgirish 146044961713Sgirish MUTEX_EXIT(&nxgedebuglock); 146144961713Sgirish cmn_err(cmn_level, "!%s %s\n", 146244961713Sgirish prefix_buffer, msg_buffer); 146344961713Sgirish 146444961713Sgirish } 146544961713Sgirish } 146644961713Sgirish 146744961713Sgirish char * 146844961713Sgirish nxge_dump_packet(char *addr, int size) 146944961713Sgirish { 147044961713Sgirish uchar_t *ap = (uchar_t *)addr; 147144961713Sgirish int i; 147244961713Sgirish static char etherbuf[1024]; 147344961713Sgirish char *cp = etherbuf; 147444961713Sgirish char digits[] = "0123456789abcdef"; 147544961713Sgirish 147644961713Sgirish if (!size) 147744961713Sgirish size = 60; 147844961713Sgirish 147944961713Sgirish if (size > MAX_DUMP_SZ) { 148044961713Sgirish /* Dump the leading bytes */ 148144961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 148244961713Sgirish if (*ap > 0x0f) 148344961713Sgirish *cp++ = digits[*ap >> 4]; 148444961713Sgirish *cp++ = digits[*ap++ & 0xf]; 148544961713Sgirish *cp++ = ':'; 148644961713Sgirish } 148744961713Sgirish for (i = 0; i < 20; i++) 148844961713Sgirish *cp++ = '.'; 148944961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 149044961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 149144961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 149244961713Sgirish if (*ap > 0x0f) 149344961713Sgirish *cp++ = digits[*ap >> 4]; 149444961713Sgirish *cp++ = digits[*ap++ & 0xf]; 149544961713Sgirish *cp++ = ':'; 149644961713Sgirish } 149744961713Sgirish } else { 149844961713Sgirish for (i = 0; i < size; i++) { 149944961713Sgirish if (*ap > 0x0f) 150044961713Sgirish *cp++ = digits[*ap >> 4]; 150144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 150244961713Sgirish *cp++ = ':'; 150344961713Sgirish } 150444961713Sgirish } 150544961713Sgirish *--cp = 0; 150644961713Sgirish return (etherbuf); 150744961713Sgirish } 150844961713Sgirish 150944961713Sgirish #ifdef NXGE_DEBUG 151044961713Sgirish static void 151144961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 151244961713Sgirish { 151344961713Sgirish ddi_acc_handle_t cfg_handle; 151444961713Sgirish p_pci_cfg_t cfg_ptr; 151544961713Sgirish ddi_acc_handle_t dev_handle; 151644961713Sgirish char *dev_ptr; 151744961713Sgirish ddi_acc_handle_t pci_config_handle; 151844961713Sgirish uint32_t regval; 151944961713Sgirish int i; 152044961713Sgirish 152144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 152244961713Sgirish 152344961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 152444961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 152544961713Sgirish 152644961713Sgirish if (nxgep->niu_type == NEPTUNE) { 152744961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 152844961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 152944961713Sgirish 153044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 153144961713Sgirish "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 153244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 153344961713Sgirish "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 153444961713Sgirish &cfg_ptr->vendorid)); 153544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 153644961713Sgirish "\tvendorid 0x%x devid 0x%x", 153744961713Sgirish NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 153844961713Sgirish NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 153944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 154044961713Sgirish "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 154144961713Sgirish "bar1c 0x%x", 154244961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 154344961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 154444961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 154544961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 154644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 154744961713Sgirish "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 154844961713Sgirish "base 28 0x%x bar2c 0x%x\n", 154944961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 155044961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 155144961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 155244961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 155344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 155444961713Sgirish "\nNeptune PCI BAR: base30 0x%x\n", 155544961713Sgirish NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 155644961713Sgirish 155744961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 155844961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 155944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 156044961713Sgirish "first 0x%llx second 0x%llx third 0x%llx " 156144961713Sgirish "last 0x%llx ", 156244961713Sgirish NXGE_PIO_READ64(dev_handle, 156344961713Sgirish (uint64_t *)(dev_ptr + 0), 0), 156444961713Sgirish NXGE_PIO_READ64(dev_handle, 156544961713Sgirish (uint64_t *)(dev_ptr + 8), 0), 156644961713Sgirish NXGE_PIO_READ64(dev_handle, 156744961713Sgirish (uint64_t *)(dev_ptr + 16), 0), 156844961713Sgirish NXGE_PIO_READ64(cfg_handle, 156944961713Sgirish (uint64_t *)(dev_ptr + 24), 0))); 157044961713Sgirish } 157144961713Sgirish } 157244961713Sgirish 157344961713Sgirish #endif 157444961713Sgirish 157544961713Sgirish static void 157644961713Sgirish nxge_suspend(p_nxge_t nxgep) 157744961713Sgirish { 157844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 157944961713Sgirish 158044961713Sgirish nxge_intrs_disable(nxgep); 158144961713Sgirish nxge_destroy_dev(nxgep); 158244961713Sgirish 158344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 158444961713Sgirish } 158544961713Sgirish 158644961713Sgirish static nxge_status_t 158744961713Sgirish nxge_resume(p_nxge_t nxgep) 158844961713Sgirish { 158944961713Sgirish nxge_status_t status = NXGE_OK; 159044961713Sgirish 159144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 159244961713Sgirish nxgep->suspended = DDI_RESUME; 159344961713Sgirish 159444961713Sgirish nxge_global_reset(nxgep); 159544961713Sgirish nxgep->suspended = 0; 159644961713Sgirish 159744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 159844961713Sgirish "<== nxge_resume status = 0x%x", status)); 159944961713Sgirish return (status); 160044961713Sgirish } 160144961713Sgirish 160244961713Sgirish static nxge_status_t 160344961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 160444961713Sgirish { 160544961713Sgirish nxge_status_t status = NXGE_OK; 160644961713Sgirish 160744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 160844961713Sgirish nxgep->mac.portnum)); 160944961713Sgirish 161044961713Sgirish status = nxge_xcvr_find(nxgep); 161144961713Sgirish if (status != NXGE_OK) { 161244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 161344961713Sgirish " nxge_setup_dev status " 161444961713Sgirish " (xcvr find 0x%08x)", status)); 161544961713Sgirish goto nxge_setup_dev_exit; 161644961713Sgirish } 161744961713Sgirish 161844961713Sgirish status = nxge_link_init(nxgep); 161914ea4bb7Ssd 162014ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 162114ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 162214ea4bb7Ssd "port%d Bad register acc handle", nxgep->mac.portnum)); 162314ea4bb7Ssd status = NXGE_ERROR; 162414ea4bb7Ssd } 162514ea4bb7Ssd 162644961713Sgirish if (status != NXGE_OK) { 162744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 162844961713Sgirish " nxge_setup_dev status " 162944961713Sgirish "(xcvr init 0x%08x)", status)); 163044961713Sgirish goto nxge_setup_dev_exit; 163144961713Sgirish } 163244961713Sgirish 163344961713Sgirish nxge_setup_dev_exit: 163444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 163544961713Sgirish "<== nxge_setup_dev port %d status = 0x%08x", 163644961713Sgirish nxgep->mac.portnum, status)); 163744961713Sgirish 163844961713Sgirish return (status); 163944961713Sgirish } 164044961713Sgirish 164144961713Sgirish static void 164244961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 164344961713Sgirish { 164444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 164544961713Sgirish 164644961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 164744961713Sgirish 164844961713Sgirish (void) nxge_hw_stop(nxgep); 164944961713Sgirish 165044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 165144961713Sgirish } 165244961713Sgirish 165344961713Sgirish static nxge_status_t 165444961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 165544961713Sgirish { 165644961713Sgirish int ddi_status = DDI_SUCCESS; 165744961713Sgirish uint_t count; 165844961713Sgirish ddi_dma_cookie_t cookie; 165944961713Sgirish uint_t iommu_pagesize; 166044961713Sgirish nxge_status_t status = NXGE_OK; 166144961713Sgirish 166244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 166344961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 166444961713Sgirish if (nxgep->niu_type != N2_NIU) { 166544961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 166644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 166744961713Sgirish " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 166844961713Sgirish " default_block_size %d iommu_pagesize %d", 166944961713Sgirish nxgep->sys_page_sz, 167044961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 167144961713Sgirish nxgep->rx_default_block_size, 167244961713Sgirish iommu_pagesize)); 167344961713Sgirish 167444961713Sgirish if (iommu_pagesize != 0) { 167544961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 167644961713Sgirish if (iommu_pagesize > 0x4000) 167744961713Sgirish nxgep->sys_page_sz = 0x4000; 167844961713Sgirish } else { 167944961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 168044961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 168144961713Sgirish } 168244961713Sgirish } 168344961713Sgirish } 168444961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 168544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 168644961713Sgirish "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 168744961713Sgirish "default_block_size %d page mask %d", 168844961713Sgirish nxgep->sys_page_sz, 168944961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 169044961713Sgirish nxgep->rx_default_block_size, 169144961713Sgirish nxgep->sys_page_mask)); 169244961713Sgirish 169344961713Sgirish 169444961713Sgirish switch (nxgep->sys_page_sz) { 169544961713Sgirish default: 169644961713Sgirish nxgep->sys_page_sz = 0x1000; 169744961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 169844961713Sgirish nxgep->rx_default_block_size = 0x1000; 169944961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 170044961713Sgirish break; 170144961713Sgirish case 0x1000: 170244961713Sgirish nxgep->rx_default_block_size = 0x1000; 170344961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 170444961713Sgirish break; 170544961713Sgirish case 0x2000: 170644961713Sgirish nxgep->rx_default_block_size = 0x2000; 170744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 170844961713Sgirish break; 170944961713Sgirish case 0x4000: 171044961713Sgirish nxgep->rx_default_block_size = 0x4000; 171144961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 171244961713Sgirish break; 171344961713Sgirish case 0x8000: 171444961713Sgirish nxgep->rx_default_block_size = 0x8000; 171544961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 171644961713Sgirish break; 171744961713Sgirish } 171844961713Sgirish 171944961713Sgirish #ifndef USE_RX_BIG_BUF 172044961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 172144961713Sgirish #else 172244961713Sgirish nxgep->rx_default_block_size = 0x2000; 172344961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 172444961713Sgirish #endif 172544961713Sgirish /* 172644961713Sgirish * Get the system DMA burst size. 172744961713Sgirish */ 172844961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 172944961713Sgirish DDI_DMA_DONTWAIT, 0, 173044961713Sgirish &nxgep->dmasparehandle); 173144961713Sgirish if (ddi_status != DDI_SUCCESS) { 173244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 173344961713Sgirish "ddi_dma_alloc_handle: failed " 173444961713Sgirish " status 0x%x", ddi_status)); 173544961713Sgirish goto nxge_get_soft_properties_exit; 173644961713Sgirish } 173744961713Sgirish 173844961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 173944961713Sgirish (caddr_t)nxgep->dmasparehandle, 174044961713Sgirish sizeof (nxgep->dmasparehandle), 174144961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 174244961713Sgirish DDI_DMA_DONTWAIT, 0, 174344961713Sgirish &cookie, &count); 174444961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 174544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 174644961713Sgirish "Binding spare handle to find system" 174744961713Sgirish " burstsize failed.")); 174844961713Sgirish ddi_status = DDI_FAILURE; 174944961713Sgirish goto nxge_get_soft_properties_fail1; 175044961713Sgirish } 175144961713Sgirish 175244961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 175344961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 175444961713Sgirish 175544961713Sgirish nxge_get_soft_properties_fail1: 175644961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 175744961713Sgirish 175844961713Sgirish nxge_get_soft_properties_exit: 175944961713Sgirish 176044961713Sgirish if (ddi_status != DDI_SUCCESS) 176144961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 176244961713Sgirish 176344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 176444961713Sgirish "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 176544961713Sgirish return (status); 176644961713Sgirish } 176744961713Sgirish 176844961713Sgirish static nxge_status_t 176944961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 177044961713Sgirish { 177144961713Sgirish nxge_status_t status = NXGE_OK; 177244961713Sgirish 177344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 177444961713Sgirish 177544961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 177644961713Sgirish if (status != NXGE_OK) { 177744961713Sgirish return (NXGE_ERROR); 177844961713Sgirish } 177944961713Sgirish 178044961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 178144961713Sgirish if (status != NXGE_OK) { 178244961713Sgirish nxge_free_rx_mem_pool(nxgep); 178344961713Sgirish return (NXGE_ERROR); 178444961713Sgirish } 178544961713Sgirish 178644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 178744961713Sgirish return (NXGE_OK); 178844961713Sgirish } 178944961713Sgirish 179044961713Sgirish static void 179144961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 179244961713Sgirish { 179344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 179444961713Sgirish 179544961713Sgirish nxge_free_rx_mem_pool(nxgep); 179644961713Sgirish nxge_free_tx_mem_pool(nxgep); 179744961713Sgirish 179844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 179944961713Sgirish } 180044961713Sgirish 180144961713Sgirish static nxge_status_t 180244961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 180344961713Sgirish { 180444961713Sgirish int i, j; 180544961713Sgirish uint32_t ndmas, st_rdc; 180644961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 180744961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 180844961713Sgirish p_nxge_dma_pool_t dma_poolp; 180944961713Sgirish p_nxge_dma_common_t *dma_buf_p; 181044961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 181144961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 181244961713Sgirish size_t rx_buf_alloc_size; 181344961713Sgirish size_t rx_cntl_alloc_size; 181444961713Sgirish uint32_t *num_chunks; /* per dma */ 181544961713Sgirish nxge_status_t status = NXGE_OK; 181644961713Sgirish 181744961713Sgirish uint32_t nxge_port_rbr_size; 181844961713Sgirish uint32_t nxge_port_rbr_spare_size; 181944961713Sgirish uint32_t nxge_port_rcr_size; 182044961713Sgirish 182144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 182244961713Sgirish 182344961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 182444961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 182544961713Sgirish st_rdc = p_cfgp->start_rdc; 182644961713Sgirish ndmas = p_cfgp->max_rdcs; 182744961713Sgirish 182844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 182944961713Sgirish " nxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 183044961713Sgirish 183144961713Sgirish /* 183244961713Sgirish * Allocate memory for each receive DMA channel. 183344961713Sgirish */ 183444961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 183544961713Sgirish KM_SLEEP); 183644961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 183744961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 183844961713Sgirish 183944961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 184044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 184144961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 184244961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 184344961713Sgirish 184444961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 184544961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 184644961713Sgirish 184744961713Sgirish /* 184844961713Sgirish * Assume that each DMA channel will be configured with default 184944961713Sgirish * block size. 185044961713Sgirish * rbr block counts are mod of batch count (16). 185144961713Sgirish */ 185244961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 185344961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 185444961713Sgirish 185544961713Sgirish if (!nxge_port_rbr_size) { 185644961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 185744961713Sgirish } 185844961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 185944961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 186044961713Sgirish (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 186144961713Sgirish } 186244961713Sgirish 186344961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 186444961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 186544961713Sgirish 186644961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 186744961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 186844961713Sgirish (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 186944961713Sgirish } 187044961713Sgirish 187144961713Sgirish /* 187244961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 187344961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 187444961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 187544961713Sgirish * function). 187644961713Sgirish */ 187744961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 187844961713Sgirish if (nxgep->niu_type == N2_NIU) { 187944961713Sgirish nxge_port_rbr_spare_size = 0; 188044961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 188144961713Sgirish (!ISP2(nxge_port_rbr_size))) { 188244961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 188344961713Sgirish } 188444961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 188544961713Sgirish (!ISP2(nxge_port_rcr_size))) { 188644961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 188744961713Sgirish } 188844961713Sgirish } 188944961713Sgirish #endif 189044961713Sgirish 189144961713Sgirish rx_buf_alloc_size = (nxgep->rx_default_block_size * 189244961713Sgirish (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 189344961713Sgirish 189444961713Sgirish /* 189544961713Sgirish * Addresses of receive block ring, receive completion ring and the 189644961713Sgirish * mailbox must be all cache-aligned (64 bytes). 189744961713Sgirish */ 189844961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 189944961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 190044961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 190144961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 190244961713Sgirish 190344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 190444961713Sgirish "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 190544961713Sgirish "nxge_port_rcr_size = %d " 190644961713Sgirish "rx_cntl_alloc_size = %d", 190744961713Sgirish nxge_port_rbr_size, nxge_port_rbr_spare_size, 190844961713Sgirish nxge_port_rcr_size, 190944961713Sgirish rx_cntl_alloc_size)); 191044961713Sgirish 191144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 191244961713Sgirish if (nxgep->niu_type == N2_NIU) { 191344961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 191444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 191544961713Sgirish "==> nxge_alloc_rx_mem_pool: " 191644961713Sgirish " must be power of 2")); 191744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 191844961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 191944961713Sgirish } 192044961713Sgirish 192144961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 192244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 192344961713Sgirish "==> nxge_alloc_rx_mem_pool: " 192444961713Sgirish " limit size to 4M")); 192544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 192644961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 192744961713Sgirish } 192844961713Sgirish 192944961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 193044961713Sgirish rx_cntl_alloc_size = 0x2000; 193144961713Sgirish } 193244961713Sgirish } 193344961713Sgirish #endif 193444961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 193544961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 193644961713Sgirish 193744961713Sgirish /* 193844961713Sgirish * Allocate memory for receive buffers and descriptor rings. 193944961713Sgirish * Replace allocation functions with interface functions provided 194044961713Sgirish * by the partition manager when it is available. 194144961713Sgirish */ 194244961713Sgirish /* 194344961713Sgirish * Allocate memory for the receive buffer blocks. 194444961713Sgirish */ 194544961713Sgirish for (i = 0; i < ndmas; i++) { 194644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 194744961713Sgirish " nxge_alloc_rx_mem_pool to alloc mem: " 194844961713Sgirish " dma %d dma_buf_p %llx &dma_buf_p %llx", 194944961713Sgirish i, dma_buf_p[i], &dma_buf_p[i])); 195044961713Sgirish num_chunks[i] = 0; 195144961713Sgirish status = nxge_alloc_rx_buf_dma(nxgep, st_rdc, &dma_buf_p[i], 195244961713Sgirish rx_buf_alloc_size, 195344961713Sgirish nxgep->rx_default_block_size, &num_chunks[i]); 195444961713Sgirish if (status != NXGE_OK) { 195544961713Sgirish break; 195644961713Sgirish } 195744961713Sgirish st_rdc++; 195844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 195944961713Sgirish " nxge_alloc_rx_mem_pool DONE alloc mem: " 196044961713Sgirish "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 196144961713Sgirish dma_buf_p[i], &dma_buf_p[i])); 196244961713Sgirish } 196344961713Sgirish if (i < ndmas) { 196444961713Sgirish goto nxge_alloc_rx_mem_fail1; 196544961713Sgirish } 196644961713Sgirish /* 196744961713Sgirish * Allocate memory for descriptor rings and mailbox. 196844961713Sgirish */ 196944961713Sgirish st_rdc = p_cfgp->start_rdc; 197044961713Sgirish for (j = 0; j < ndmas; j++) { 197144961713Sgirish status = nxge_alloc_rx_cntl_dma(nxgep, st_rdc, &dma_cntl_p[j], 197244961713Sgirish rx_cntl_alloc_size); 197344961713Sgirish if (status != NXGE_OK) { 197444961713Sgirish break; 197544961713Sgirish } 197644961713Sgirish st_rdc++; 197744961713Sgirish } 197844961713Sgirish if (j < ndmas) { 197944961713Sgirish goto nxge_alloc_rx_mem_fail2; 198044961713Sgirish } 198144961713Sgirish 198244961713Sgirish dma_poolp->ndmas = ndmas; 198344961713Sgirish dma_poolp->num_chunks = num_chunks; 198444961713Sgirish dma_poolp->buf_allocated = B_TRUE; 198544961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 198644961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 198744961713Sgirish 198844961713Sgirish dma_cntl_poolp->ndmas = ndmas; 198944961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 199044961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 199144961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 199244961713Sgirish 199344961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 199444961713Sgirish 199544961713Sgirish nxge_alloc_rx_mem_fail2: 199644961713Sgirish /* Free control buffers */ 199744961713Sgirish j--; 199844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 199944961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 200044961713Sgirish for (; j >= 0; j--) { 200144961713Sgirish nxge_free_rx_cntl_dma(nxgep, 200244961713Sgirish (p_nxge_dma_common_t)dma_cntl_p[i]); 200344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 200444961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", 200544961713Sgirish j)); 200644961713Sgirish } 200744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 200844961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 200944961713Sgirish 201044961713Sgirish nxge_alloc_rx_mem_fail1: 201144961713Sgirish /* Free data buffers */ 201244961713Sgirish i--; 201344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 201444961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 201544961713Sgirish for (; i >= 0; i--) { 201644961713Sgirish nxge_free_rx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 201744961713Sgirish num_chunks[i]); 201844961713Sgirish } 201944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 202044961713Sgirish "==> nxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 202144961713Sgirish 202244961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 202344961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 202444961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 202544961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 202644961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 202744961713Sgirish 202844961713Sgirish nxge_alloc_rx_mem_pool_exit: 202944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 203044961713Sgirish "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 203144961713Sgirish 203244961713Sgirish return (status); 203344961713Sgirish } 203444961713Sgirish 203544961713Sgirish static void 203644961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 203744961713Sgirish { 203844961713Sgirish uint32_t i, ndmas; 203944961713Sgirish p_nxge_dma_pool_t dma_poolp; 204044961713Sgirish p_nxge_dma_common_t *dma_buf_p; 204144961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 204244961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 204344961713Sgirish uint32_t *num_chunks; 204444961713Sgirish 204544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 204644961713Sgirish 204744961713Sgirish dma_poolp = nxgep->rx_buf_pool_p; 204844961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 204944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 205044961713Sgirish "<== nxge_free_rx_mem_pool " 205144961713Sgirish "(null rx buf pool or buf not allocated")); 205244961713Sgirish return; 205344961713Sgirish } 205444961713Sgirish 205544961713Sgirish dma_cntl_poolp = nxgep->rx_cntl_pool_p; 205644961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 205744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 205844961713Sgirish "<== nxge_free_rx_mem_pool " 205944961713Sgirish "(null rx cntl buf pool or cntl buf not allocated")); 206044961713Sgirish return; 206144961713Sgirish } 206244961713Sgirish 206344961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 206444961713Sgirish num_chunks = dma_poolp->num_chunks; 206544961713Sgirish 206644961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 206744961713Sgirish ndmas = dma_cntl_poolp->ndmas; 206844961713Sgirish 206944961713Sgirish for (i = 0; i < ndmas; i++) { 207044961713Sgirish nxge_free_rx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 207144961713Sgirish } 207244961713Sgirish 207344961713Sgirish for (i = 0; i < ndmas; i++) { 207444961713Sgirish nxge_free_rx_cntl_dma(nxgep, dma_cntl_p[i]); 207544961713Sgirish } 207644961713Sgirish 207744961713Sgirish for (i = 0; i < ndmas; i++) { 207844961713Sgirish KMEM_FREE(dma_buf_p[i], 207944961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 208044961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 208144961713Sgirish } 208244961713Sgirish 208344961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 208444961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 208544961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 208644961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 208744961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 208844961713Sgirish 208944961713Sgirish nxgep->rx_buf_pool_p = NULL; 209044961713Sgirish nxgep->rx_cntl_pool_p = NULL; 209144961713Sgirish 209244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 209344961713Sgirish } 209444961713Sgirish 209544961713Sgirish 209644961713Sgirish static nxge_status_t 209744961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 209844961713Sgirish p_nxge_dma_common_t *dmap, 209944961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 210044961713Sgirish { 210144961713Sgirish p_nxge_dma_common_t rx_dmap; 210244961713Sgirish nxge_status_t status = NXGE_OK; 210344961713Sgirish size_t total_alloc_size; 210444961713Sgirish size_t allocated = 0; 210544961713Sgirish int i, size_index, array_size; 210644961713Sgirish 210744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 210844961713Sgirish 210944961713Sgirish rx_dmap = (p_nxge_dma_common_t) 211044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 211144961713Sgirish KM_SLEEP); 211244961713Sgirish 211344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 211444961713Sgirish " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 211544961713Sgirish dma_channel, alloc_size, block_size, dmap)); 211644961713Sgirish 211744961713Sgirish total_alloc_size = alloc_size; 211844961713Sgirish 211944961713Sgirish #if defined(RX_USE_RECLAIM_POST) 212044961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 212144961713Sgirish #endif 212244961713Sgirish 212344961713Sgirish i = 0; 212444961713Sgirish size_index = 0; 212544961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 212644961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 212744961713Sgirish (size_index < array_size)) 212844961713Sgirish size_index++; 212944961713Sgirish if (size_index >= array_size) { 213044961713Sgirish size_index = array_size - 1; 213144961713Sgirish } 213244961713Sgirish 213344961713Sgirish while ((allocated < total_alloc_size) && 213444961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 213544961713Sgirish rx_dmap[i].dma_chunk_index = i; 213644961713Sgirish rx_dmap[i].block_size = block_size; 213744961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 213844961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 213944961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 214044961713Sgirish rx_dmap[i].dma_channel = dma_channel; 214144961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 214244961713Sgirish 214344961713Sgirish /* 214444961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 214544961713Sgirish * needs to call Hypervisor api to set up 214644961713Sgirish * logical pages. 214744961713Sgirish */ 214844961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 214944961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 215044961713Sgirish } 215144961713Sgirish 215244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 215344961713Sgirish "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 215444961713Sgirish "i %d nblocks %d alength %d", 215544961713Sgirish dma_channel, i, &rx_dmap[i], block_size, 215644961713Sgirish i, rx_dmap[i].nblocks, 215744961713Sgirish rx_dmap[i].alength)); 215844961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 215944961713Sgirish &nxge_rx_dma_attr, 216044961713Sgirish rx_dmap[i].alength, 216144961713Sgirish &nxge_dev_buf_dma_acc_attr, 216244961713Sgirish DDI_DMA_READ | DDI_DMA_STREAMING, 216344961713Sgirish (p_nxge_dma_common_t)(&rx_dmap[i])); 216444961713Sgirish if (status != NXGE_OK) { 216544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 216644961713Sgirish " nxge_alloc_rx_buf_dma: Alloc Failed ")); 216744961713Sgirish size_index--; 216844961713Sgirish } else { 216944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 217044961713Sgirish " alloc_rx_buf_dma allocated rdc %d " 217144961713Sgirish "chunk %d size %x dvma %x bufp %llx ", 217244961713Sgirish dma_channel, i, rx_dmap[i].alength, 217344961713Sgirish rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 217444961713Sgirish i++; 217544961713Sgirish allocated += alloc_sizes[size_index]; 217644961713Sgirish } 217744961713Sgirish } 217844961713Sgirish 217944961713Sgirish 218044961713Sgirish if (allocated < total_alloc_size) { 218144961713Sgirish goto nxge_alloc_rx_mem_fail1; 218244961713Sgirish } 218344961713Sgirish 218444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 218544961713Sgirish " alloc_rx_buf_dma rdc %d allocated %d chunks", 218644961713Sgirish dma_channel, i)); 218744961713Sgirish *num_chunks = i; 218844961713Sgirish *dmap = rx_dmap; 218944961713Sgirish 219044961713Sgirish goto nxge_alloc_rx_mem_exit; 219144961713Sgirish 219244961713Sgirish nxge_alloc_rx_mem_fail1: 219344961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 219444961713Sgirish 219544961713Sgirish nxge_alloc_rx_mem_exit: 219644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 219744961713Sgirish "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 219844961713Sgirish 219944961713Sgirish return (status); 220044961713Sgirish } 220144961713Sgirish 220244961713Sgirish /*ARGSUSED*/ 220344961713Sgirish static void 220444961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 220544961713Sgirish uint32_t num_chunks) 220644961713Sgirish { 220744961713Sgirish int i; 220844961713Sgirish 220944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 221044961713Sgirish "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 221144961713Sgirish 221244961713Sgirish for (i = 0; i < num_chunks; i++) { 221344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 221444961713Sgirish "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 221544961713Sgirish i, dmap)); 221644961713Sgirish nxge_dma_mem_free(dmap++); 221744961713Sgirish } 221844961713Sgirish 221944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 222044961713Sgirish } 222144961713Sgirish 222244961713Sgirish /*ARGSUSED*/ 222344961713Sgirish static nxge_status_t 222444961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 222544961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 222644961713Sgirish { 222744961713Sgirish p_nxge_dma_common_t rx_dmap; 222844961713Sgirish nxge_status_t status = NXGE_OK; 222944961713Sgirish 223044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 223144961713Sgirish 223244961713Sgirish rx_dmap = (p_nxge_dma_common_t) 223344961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 223444961713Sgirish 223544961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 223644961713Sgirish 223744961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 223844961713Sgirish &nxge_desc_dma_attr, 223944961713Sgirish size, 224044961713Sgirish &nxge_dev_desc_dma_acc_attr, 224144961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 224244961713Sgirish rx_dmap); 224344961713Sgirish if (status != NXGE_OK) { 224444961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 224544961713Sgirish } 224644961713Sgirish 224744961713Sgirish *dmap = rx_dmap; 224844961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 224944961713Sgirish 225044961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 225144961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 225244961713Sgirish 225344961713Sgirish nxge_alloc_rx_cntl_dma_exit: 225444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 225544961713Sgirish "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 225644961713Sgirish 225744961713Sgirish return (status); 225844961713Sgirish } 225944961713Sgirish 226044961713Sgirish /*ARGSUSED*/ 226144961713Sgirish static void 226244961713Sgirish nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 226344961713Sgirish { 226444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 226544961713Sgirish 226644961713Sgirish nxge_dma_mem_free(dmap); 226744961713Sgirish 226844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 226944961713Sgirish } 227044961713Sgirish 227144961713Sgirish static nxge_status_t 227244961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 227344961713Sgirish { 227444961713Sgirish nxge_status_t status = NXGE_OK; 227544961713Sgirish int i, j; 227644961713Sgirish uint32_t ndmas, st_tdc; 227744961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 227844961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 227944961713Sgirish p_nxge_dma_pool_t dma_poolp; 228044961713Sgirish p_nxge_dma_common_t *dma_buf_p; 228144961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 228244961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 228344961713Sgirish size_t tx_buf_alloc_size; 228444961713Sgirish size_t tx_cntl_alloc_size; 228544961713Sgirish uint32_t *num_chunks; /* per dma */ 2286*1f8914d5Sml uint32_t bcopy_thresh; 228744961713Sgirish 228844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 228944961713Sgirish 229044961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 229144961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 229244961713Sgirish st_tdc = p_cfgp->start_tdc; 229344961713Sgirish ndmas = p_cfgp->max_tdcs; 229444961713Sgirish 229544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool: " 229644961713Sgirish "p_cfgp 0x%016llx start_tdc %d ndmas %d nxgep->max_tdcs %d", 229744961713Sgirish p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, nxgep->max_tdcs)); 229844961713Sgirish /* 229944961713Sgirish * Allocate memory for each transmit DMA channel. 230044961713Sgirish */ 230144961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 230244961713Sgirish KM_SLEEP); 230344961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 230444961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 230544961713Sgirish 230644961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 230744961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 230844961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 230944961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 231044961713Sgirish 231144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 231244961713Sgirish /* 231344961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 231444961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 231544961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 231644961713Sgirish * function). The transmit ring is limited to 8K (includes the 231744961713Sgirish * mailbox). 231844961713Sgirish */ 231944961713Sgirish if (nxgep->niu_type == N2_NIU) { 232044961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 232144961713Sgirish (!ISP2(nxge_tx_ring_size))) { 232244961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 232344961713Sgirish } 232444961713Sgirish } 232544961713Sgirish #endif 232644961713Sgirish 232744961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 232844961713Sgirish 232944961713Sgirish /* 233044961713Sgirish * Assume that each DMA channel will be configured with default 233144961713Sgirish * transmit bufer size for copying transmit data. 233244961713Sgirish * (For packet payload over this limit, packets will not be 233344961713Sgirish * copied.) 233444961713Sgirish */ 2335*1f8914d5Sml if (nxgep->niu_type == N2_NIU) { 2336*1f8914d5Sml bcopy_thresh = TX_BCOPY_SIZE; 2337*1f8914d5Sml } else { 2338*1f8914d5Sml bcopy_thresh = nxge_bcopy_thresh; 2339*1f8914d5Sml } 2340*1f8914d5Sml tx_buf_alloc_size = (bcopy_thresh * nxge_tx_ring_size); 234144961713Sgirish 234244961713Sgirish /* 234344961713Sgirish * Addresses of transmit descriptor ring and the 234444961713Sgirish * mailbox must be all cache-aligned (64 bytes). 234544961713Sgirish */ 234644961713Sgirish tx_cntl_alloc_size = nxge_tx_ring_size; 234744961713Sgirish tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 234844961713Sgirish tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 234944961713Sgirish 235044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 235144961713Sgirish if (nxgep->niu_type == N2_NIU) { 235244961713Sgirish if (!ISP2(tx_buf_alloc_size)) { 235344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 235444961713Sgirish "==> nxge_alloc_tx_mem_pool: " 235544961713Sgirish " must be power of 2")); 235644961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 235744961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 235844961713Sgirish } 235944961713Sgirish 236044961713Sgirish if (tx_buf_alloc_size > (1 << 22)) { 236144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 236244961713Sgirish "==> nxge_alloc_tx_mem_pool: " 236344961713Sgirish " limit size to 4M")); 236444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 236544961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 236644961713Sgirish } 236744961713Sgirish 236844961713Sgirish if (tx_cntl_alloc_size < 0x2000) { 236944961713Sgirish tx_cntl_alloc_size = 0x2000; 237044961713Sgirish } 237144961713Sgirish } 237244961713Sgirish #endif 237344961713Sgirish 237444961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 237544961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 237644961713Sgirish 237744961713Sgirish /* 237844961713Sgirish * Allocate memory for transmit buffers and descriptor rings. 237944961713Sgirish * Replace allocation functions with interface functions provided 238044961713Sgirish * by the partition manager when it is available. 238144961713Sgirish * 238244961713Sgirish * Allocate memory for the transmit buffer pool. 238344961713Sgirish */ 238444961713Sgirish for (i = 0; i < ndmas; i++) { 238544961713Sgirish num_chunks[i] = 0; 238644961713Sgirish status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i], 238744961713Sgirish tx_buf_alloc_size, 2388*1f8914d5Sml bcopy_thresh, &num_chunks[i]); 238944961713Sgirish if (status != NXGE_OK) { 239044961713Sgirish break; 239144961713Sgirish } 239244961713Sgirish st_tdc++; 239344961713Sgirish } 239444961713Sgirish if (i < ndmas) { 239544961713Sgirish goto nxge_alloc_tx_mem_pool_fail1; 239644961713Sgirish } 239744961713Sgirish 239844961713Sgirish st_tdc = p_cfgp->start_tdc; 239944961713Sgirish /* 240044961713Sgirish * Allocate memory for descriptor rings and mailbox. 240144961713Sgirish */ 240244961713Sgirish for (j = 0; j < ndmas; j++) { 240344961713Sgirish status = nxge_alloc_tx_cntl_dma(nxgep, st_tdc, &dma_cntl_p[j], 240444961713Sgirish tx_cntl_alloc_size); 240544961713Sgirish if (status != NXGE_OK) { 240644961713Sgirish break; 240744961713Sgirish } 240844961713Sgirish st_tdc++; 240944961713Sgirish } 241044961713Sgirish if (j < ndmas) { 241144961713Sgirish goto nxge_alloc_tx_mem_pool_fail2; 241244961713Sgirish } 241344961713Sgirish 241444961713Sgirish dma_poolp->ndmas = ndmas; 241544961713Sgirish dma_poolp->num_chunks = num_chunks; 241644961713Sgirish dma_poolp->buf_allocated = B_TRUE; 241744961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 241844961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 241944961713Sgirish 242044961713Sgirish dma_cntl_poolp->ndmas = ndmas; 242144961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 242244961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 242344961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 242444961713Sgirish 242544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 242644961713Sgirish "==> nxge_alloc_tx_mem_pool: start_tdc %d " 242744961713Sgirish "ndmas %d poolp->ndmas %d", 242844961713Sgirish st_tdc, ndmas, dma_poolp->ndmas)); 242944961713Sgirish 243044961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 243144961713Sgirish 243244961713Sgirish nxge_alloc_tx_mem_pool_fail2: 243344961713Sgirish /* Free control buffers */ 243444961713Sgirish j--; 243544961713Sgirish for (; j >= 0; j--) { 243644961713Sgirish nxge_free_tx_cntl_dma(nxgep, 243744961713Sgirish (p_nxge_dma_common_t)dma_cntl_p[i]); 243844961713Sgirish } 243944961713Sgirish 244044961713Sgirish nxge_alloc_tx_mem_pool_fail1: 244144961713Sgirish /* Free data buffers */ 244244961713Sgirish i--; 244344961713Sgirish for (; i >= 0; i--) { 244444961713Sgirish nxge_free_tx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 244544961713Sgirish num_chunks[i]); 244644961713Sgirish } 244744961713Sgirish 244844961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 244944961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 245044961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 245144961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 245244961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 245344961713Sgirish 245444961713Sgirish nxge_alloc_tx_mem_pool_exit: 245544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 245644961713Sgirish "<== nxge_alloc_tx_mem_pool:status 0x%08x", status)); 245744961713Sgirish 245844961713Sgirish return (status); 245944961713Sgirish } 246044961713Sgirish 246144961713Sgirish static nxge_status_t 246244961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 246344961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 246444961713Sgirish size_t block_size, uint32_t *num_chunks) 246544961713Sgirish { 246644961713Sgirish p_nxge_dma_common_t tx_dmap; 246744961713Sgirish nxge_status_t status = NXGE_OK; 246844961713Sgirish size_t total_alloc_size; 246944961713Sgirish size_t allocated = 0; 247044961713Sgirish int i, size_index, array_size; 247144961713Sgirish 247244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 247344961713Sgirish 247444961713Sgirish tx_dmap = (p_nxge_dma_common_t) 247544961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 247644961713Sgirish KM_SLEEP); 247744961713Sgirish 247844961713Sgirish total_alloc_size = alloc_size; 247944961713Sgirish i = 0; 248044961713Sgirish size_index = 0; 248144961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 248244961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 248344961713Sgirish (size_index < array_size)) 248444961713Sgirish size_index++; 248544961713Sgirish if (size_index >= array_size) { 248644961713Sgirish size_index = array_size - 1; 248744961713Sgirish } 248844961713Sgirish 248944961713Sgirish while ((allocated < total_alloc_size) && 249044961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 249144961713Sgirish 249244961713Sgirish tx_dmap[i].dma_chunk_index = i; 249344961713Sgirish tx_dmap[i].block_size = block_size; 249444961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 249544961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 249644961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 249744961713Sgirish tx_dmap[i].dma_channel = dma_channel; 249844961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 249944961713Sgirish 250044961713Sgirish /* 250144961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 250244961713Sgirish * needs to call Hypervisor api to set up 250344961713Sgirish * logical pages. 250444961713Sgirish */ 250544961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 250644961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 250744961713Sgirish } 250844961713Sgirish 250944961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 251044961713Sgirish &nxge_tx_dma_attr, 251144961713Sgirish tx_dmap[i].alength, 251244961713Sgirish &nxge_dev_buf_dma_acc_attr, 251344961713Sgirish DDI_DMA_WRITE | DDI_DMA_STREAMING, 251444961713Sgirish (p_nxge_dma_common_t)(&tx_dmap[i])); 251544961713Sgirish if (status != NXGE_OK) { 251644961713Sgirish size_index--; 251744961713Sgirish } else { 251844961713Sgirish i++; 251944961713Sgirish allocated += alloc_sizes[size_index]; 252044961713Sgirish } 252144961713Sgirish } 252244961713Sgirish 252344961713Sgirish if (allocated < total_alloc_size) { 252444961713Sgirish goto nxge_alloc_tx_mem_fail1; 252544961713Sgirish } 252644961713Sgirish 252744961713Sgirish *num_chunks = i; 252844961713Sgirish *dmap = tx_dmap; 252944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 253044961713Sgirish "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 253144961713Sgirish *dmap, i)); 253244961713Sgirish goto nxge_alloc_tx_mem_exit; 253344961713Sgirish 253444961713Sgirish nxge_alloc_tx_mem_fail1: 253544961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 253644961713Sgirish 253744961713Sgirish nxge_alloc_tx_mem_exit: 253844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 253944961713Sgirish "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 254044961713Sgirish 254144961713Sgirish return (status); 254244961713Sgirish } 254344961713Sgirish 254444961713Sgirish /*ARGSUSED*/ 254544961713Sgirish static void 254644961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 254744961713Sgirish uint32_t num_chunks) 254844961713Sgirish { 254944961713Sgirish int i; 255044961713Sgirish 255144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 255244961713Sgirish 255344961713Sgirish for (i = 0; i < num_chunks; i++) { 255444961713Sgirish nxge_dma_mem_free(dmap++); 255544961713Sgirish } 255644961713Sgirish 255744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 255844961713Sgirish } 255944961713Sgirish 256044961713Sgirish /*ARGSUSED*/ 256144961713Sgirish static nxge_status_t 256244961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 256344961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 256444961713Sgirish { 256544961713Sgirish p_nxge_dma_common_t tx_dmap; 256644961713Sgirish nxge_status_t status = NXGE_OK; 256744961713Sgirish 256844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 256944961713Sgirish tx_dmap = (p_nxge_dma_common_t) 257044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 257144961713Sgirish 257244961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 257344961713Sgirish 257444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 257544961713Sgirish &nxge_desc_dma_attr, 257644961713Sgirish size, 257744961713Sgirish &nxge_dev_desc_dma_acc_attr, 257844961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 257944961713Sgirish tx_dmap); 258044961713Sgirish if (status != NXGE_OK) { 258144961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 258244961713Sgirish } 258344961713Sgirish 258444961713Sgirish *dmap = tx_dmap; 258544961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 258644961713Sgirish 258744961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 258844961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 258944961713Sgirish 259044961713Sgirish nxge_alloc_tx_cntl_dma_exit: 259144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 259244961713Sgirish "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 259344961713Sgirish 259444961713Sgirish return (status); 259544961713Sgirish } 259644961713Sgirish 259744961713Sgirish /*ARGSUSED*/ 259844961713Sgirish static void 259944961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 260044961713Sgirish { 260144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 260244961713Sgirish 260344961713Sgirish nxge_dma_mem_free(dmap); 260444961713Sgirish 260544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 260644961713Sgirish } 260744961713Sgirish 260844961713Sgirish static void 260944961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 261044961713Sgirish { 261144961713Sgirish uint32_t i, ndmas; 261244961713Sgirish p_nxge_dma_pool_t dma_poolp; 261344961713Sgirish p_nxge_dma_common_t *dma_buf_p; 261444961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 261544961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 261644961713Sgirish uint32_t *num_chunks; 261744961713Sgirish 261844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_free_tx_mem_pool")); 261944961713Sgirish 262044961713Sgirish dma_poolp = nxgep->tx_buf_pool_p; 262144961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 262244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 262344961713Sgirish "<== nxge_free_tx_mem_pool " 262444961713Sgirish "(null rx buf pool or buf not allocated")); 262544961713Sgirish return; 262644961713Sgirish } 262744961713Sgirish 262844961713Sgirish dma_cntl_poolp = nxgep->tx_cntl_pool_p; 262944961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 263044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 263144961713Sgirish "<== nxge_free_tx_mem_pool " 263244961713Sgirish "(null tx cntl buf pool or cntl buf not allocated")); 263344961713Sgirish return; 263444961713Sgirish } 263544961713Sgirish 263644961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 263744961713Sgirish num_chunks = dma_poolp->num_chunks; 263844961713Sgirish 263944961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 264044961713Sgirish ndmas = dma_cntl_poolp->ndmas; 264144961713Sgirish 264244961713Sgirish for (i = 0; i < ndmas; i++) { 264344961713Sgirish nxge_free_tx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 264444961713Sgirish } 264544961713Sgirish 264644961713Sgirish for (i = 0; i < ndmas; i++) { 264744961713Sgirish nxge_free_tx_cntl_dma(nxgep, dma_cntl_p[i]); 264844961713Sgirish } 264944961713Sgirish 265044961713Sgirish for (i = 0; i < ndmas; i++) { 265144961713Sgirish KMEM_FREE(dma_buf_p[i], 265244961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 265344961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 265444961713Sgirish } 265544961713Sgirish 265644961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 265744961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 265844961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 265944961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 266044961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 266144961713Sgirish 266244961713Sgirish nxgep->tx_buf_pool_p = NULL; 266344961713Sgirish nxgep->tx_cntl_pool_p = NULL; 266444961713Sgirish 266544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_free_tx_mem_pool")); 266644961713Sgirish } 266744961713Sgirish 266844961713Sgirish /*ARGSUSED*/ 266944961713Sgirish static nxge_status_t 267044961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 267144961713Sgirish struct ddi_dma_attr *dma_attrp, 267244961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 267344961713Sgirish p_nxge_dma_common_t dma_p) 267444961713Sgirish { 267544961713Sgirish caddr_t kaddrp; 267644961713Sgirish int ddi_status = DDI_SUCCESS; 267744961713Sgirish boolean_t contig_alloc_type; 267844961713Sgirish 267944961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 268044961713Sgirish 268144961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 268244961713Sgirish /* 268344961713Sgirish * contig_alloc_type for contiguous memory only allowed 268444961713Sgirish * for N2/NIU. 268544961713Sgirish */ 268644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 268744961713Sgirish "nxge_dma_mem_alloc: alloc type not allows (%d)", 268844961713Sgirish dma_p->contig_alloc_type)); 268944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 269044961713Sgirish } 269144961713Sgirish 269244961713Sgirish dma_p->dma_handle = NULL; 269344961713Sgirish dma_p->acc_handle = NULL; 269444961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 269544961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 269644961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 269744961713Sgirish DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 269844961713Sgirish if (ddi_status != DDI_SUCCESS) { 269944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 270044961713Sgirish "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 270144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 270244961713Sgirish } 270344961713Sgirish 270444961713Sgirish switch (contig_alloc_type) { 270544961713Sgirish case B_FALSE: 270644961713Sgirish ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, 270744961713Sgirish acc_attr_p, 270844961713Sgirish xfer_flags, 270944961713Sgirish DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 271044961713Sgirish &dma_p->acc_handle); 271144961713Sgirish if (ddi_status != DDI_SUCCESS) { 271244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 271344961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 271444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 271544961713Sgirish dma_p->dma_handle = NULL; 271644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 271744961713Sgirish } 271844961713Sgirish if (dma_p->alength < length) { 271944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 272044961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 272144961713Sgirish "< length.")); 272244961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 272344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 272444961713Sgirish dma_p->acc_handle = NULL; 272544961713Sgirish dma_p->dma_handle = NULL; 272644961713Sgirish return (NXGE_ERROR); 272744961713Sgirish } 272844961713Sgirish 272944961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 273044961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 273144961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 273244961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 273344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 273444961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 273544961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 273644961713Sgirish dma_p->ncookies)); 273744961713Sgirish if (dma_p->acc_handle) { 273844961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 273944961713Sgirish dma_p->acc_handle = NULL; 274044961713Sgirish } 274144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 274244961713Sgirish dma_p->dma_handle = NULL; 274344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 274444961713Sgirish } 274544961713Sgirish 274644961713Sgirish if (dma_p->ncookies != 1) { 274744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 274844961713Sgirish "nxge_dma_mem_alloc:ddi_dma_addr_bind " 274944961713Sgirish "> 1 cookie" 275044961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 275144961713Sgirish dma_p->ncookies)); 275244961713Sgirish if (dma_p->acc_handle) { 275344961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 275444961713Sgirish dma_p->acc_handle = NULL; 275544961713Sgirish } 275644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 275744961713Sgirish dma_p->dma_handle = NULL; 275844961713Sgirish return (NXGE_ERROR); 275944961713Sgirish } 276044961713Sgirish break; 276144961713Sgirish 276244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 276344961713Sgirish case B_TRUE: 276444961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 276544961713Sgirish if (kaddrp == NULL) { 276644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 276744961713Sgirish "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 276844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 276944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 277044961713Sgirish } 277144961713Sgirish 277244961713Sgirish dma_p->alength = length; 277344961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 277444961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 277544961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 277644961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 277744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 277844961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 277944961713Sgirish "(status 0x%x ncookies %d.)", ddi_status, 278044961713Sgirish dma_p->ncookies)); 278144961713Sgirish 278244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 278344961713Sgirish "==> nxge_dma_mem_alloc: (not mapped)" 278444961713Sgirish "length %lu (0x%x) " 278544961713Sgirish "free contig kaddrp $%p " 278644961713Sgirish "va_to_pa $%p", 278744961713Sgirish length, length, 278844961713Sgirish kaddrp, 278944961713Sgirish va_to_pa(kaddrp))); 279044961713Sgirish 279144961713Sgirish 279244961713Sgirish contig_mem_free((void *)kaddrp, length); 279344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 279444961713Sgirish 279544961713Sgirish dma_p->dma_handle = NULL; 279644961713Sgirish dma_p->acc_handle = NULL; 279744961713Sgirish dma_p->alength = NULL; 279844961713Sgirish dma_p->kaddrp = NULL; 279944961713Sgirish 280044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 280144961713Sgirish } 280244961713Sgirish 280344961713Sgirish if (dma_p->ncookies != 1 || 280444961713Sgirish (dma_p->dma_cookie.dmac_laddress == NULL)) { 280544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280644961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 280744961713Sgirish "cookie or " 280844961713Sgirish "dmac_laddress is NULL $%p size %d " 280944961713Sgirish " (status 0x%x ncookies %d.)", 281044961713Sgirish ddi_status, 281144961713Sgirish dma_p->dma_cookie.dmac_laddress, 281244961713Sgirish dma_p->dma_cookie.dmac_size, 281344961713Sgirish dma_p->ncookies)); 281444961713Sgirish 281544961713Sgirish contig_mem_free((void *)kaddrp, length); 281644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 281744961713Sgirish 281844961713Sgirish dma_p->alength = 0; 281944961713Sgirish dma_p->dma_handle = NULL; 282044961713Sgirish dma_p->acc_handle = NULL; 282144961713Sgirish dma_p->kaddrp = NULL; 282244961713Sgirish 282344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 282444961713Sgirish } 282544961713Sgirish break; 282644961713Sgirish 282744961713Sgirish #else 282844961713Sgirish case B_TRUE: 282944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 283044961713Sgirish "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 283144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 283244961713Sgirish #endif 283344961713Sgirish } 283444961713Sgirish 283544961713Sgirish dma_p->kaddrp = kaddrp; 283644961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 283744961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 283844961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 283944961713Sgirish dma_p->last_ioaddr_pp = 284044961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress + 284144961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 284244961713Sgirish 284344961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 284444961713Sgirish 284544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 284644961713Sgirish dma_p->orig_ioaddr_pp = 284744961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress; 284844961713Sgirish dma_p->orig_alength = length; 284944961713Sgirish dma_p->orig_kaddrp = kaddrp; 285044961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 285144961713Sgirish #endif 285244961713Sgirish 285344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 285444961713Sgirish "dma buffer allocated: dma_p $%p " 285544961713Sgirish "return dmac_ladress from cookie $%p cookie dmac_size %d " 285644961713Sgirish "dma_p->ioaddr_p $%p " 285744961713Sgirish "dma_p->orig_ioaddr_p $%p " 285844961713Sgirish "orig_vatopa $%p " 285944961713Sgirish "alength %d (0x%x) " 286044961713Sgirish "kaddrp $%p " 286144961713Sgirish "length %d (0x%x)", 286244961713Sgirish dma_p, 286344961713Sgirish dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 286444961713Sgirish dma_p->ioaddr_pp, 286544961713Sgirish dma_p->orig_ioaddr_pp, 286644961713Sgirish dma_p->orig_vatopa, 286744961713Sgirish dma_p->alength, dma_p->alength, 286844961713Sgirish kaddrp, 286944961713Sgirish length, length)); 287044961713Sgirish 287144961713Sgirish return (NXGE_OK); 287244961713Sgirish } 287344961713Sgirish 287444961713Sgirish static void 287544961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 287644961713Sgirish { 287744961713Sgirish if (dma_p->dma_handle != NULL) { 287844961713Sgirish if (dma_p->ncookies) { 287944961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 288044961713Sgirish dma_p->ncookies = 0; 288144961713Sgirish } 288244961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 288344961713Sgirish dma_p->dma_handle = NULL; 288444961713Sgirish } 288544961713Sgirish 288644961713Sgirish if (dma_p->acc_handle != NULL) { 288744961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 288844961713Sgirish dma_p->acc_handle = NULL; 288944961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 289044961713Sgirish } 289144961713Sgirish 289244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 289344961713Sgirish if (dma_p->contig_alloc_type && 289444961713Sgirish dma_p->orig_kaddrp && dma_p->orig_alength) { 289544961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 289644961713Sgirish "kaddrp $%p (orig_kaddrp $%p)" 289744961713Sgirish "mem type %d ", 289844961713Sgirish "orig_alength %d " 289944961713Sgirish "alength 0x%x (%d)", 290044961713Sgirish dma_p->kaddrp, 290144961713Sgirish dma_p->orig_kaddrp, 290244961713Sgirish dma_p->contig_alloc_type, 290344961713Sgirish dma_p->orig_alength, 290444961713Sgirish dma_p->alength, dma_p->alength)); 290544961713Sgirish 290644961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 290744961713Sgirish dma_p->orig_alength = NULL; 290844961713Sgirish dma_p->orig_kaddrp = NULL; 290944961713Sgirish dma_p->contig_alloc_type = B_FALSE; 291044961713Sgirish } 291144961713Sgirish #endif 291244961713Sgirish dma_p->kaddrp = NULL; 291344961713Sgirish dma_p->alength = NULL; 291444961713Sgirish } 291544961713Sgirish 291644961713Sgirish /* 291744961713Sgirish * nxge_m_start() -- start transmitting and receiving. 291844961713Sgirish * 291944961713Sgirish * This function is called by the MAC layer when the first 292044961713Sgirish * stream is open to prepare the hardware ready for sending 292144961713Sgirish * and transmitting packets. 292244961713Sgirish */ 292344961713Sgirish static int 292444961713Sgirish nxge_m_start(void *arg) 292544961713Sgirish { 292644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 292744961713Sgirish 292844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 292944961713Sgirish 293044961713Sgirish MUTEX_ENTER(nxgep->genlock); 293114ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 293244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 293344961713Sgirish "<== nxge_m_start: initialization failed")); 293444961713Sgirish MUTEX_EXIT(nxgep->genlock); 293544961713Sgirish return (EIO); 293644961713Sgirish } 293744961713Sgirish 293814ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 293914ea4bb7Ssd goto nxge_m_start_exit; 294044961713Sgirish /* 294144961713Sgirish * Start timer to check the system error and tx hangs 294244961713Sgirish */ 294344961713Sgirish nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state, 294444961713Sgirish NXGE_CHECK_TIMER); 294544961713Sgirish 2946a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 2947a3c5bd6dSspeer 294844961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 294944961713Sgirish 295014ea4bb7Ssd nxge_m_start_exit: 295144961713Sgirish MUTEX_EXIT(nxgep->genlock); 295244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 295344961713Sgirish return (0); 295444961713Sgirish } 295544961713Sgirish 295644961713Sgirish /* 295744961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 295844961713Sgirish */ 295944961713Sgirish static void 296044961713Sgirish nxge_m_stop(void *arg) 296144961713Sgirish { 296244961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 296344961713Sgirish 296444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 296544961713Sgirish 296644961713Sgirish if (nxgep->nxge_timerid) { 296744961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 296844961713Sgirish nxgep->nxge_timerid = 0; 296944961713Sgirish } 2970a3c5bd6dSspeer 2971a3c5bd6dSspeer MUTEX_ENTER(nxgep->genlock); 297244961713Sgirish nxge_uninit(nxgep); 297344961713Sgirish 297444961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 297544961713Sgirish 297644961713Sgirish MUTEX_EXIT(nxgep->genlock); 297744961713Sgirish 297844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 297944961713Sgirish } 298044961713Sgirish 298144961713Sgirish static int 298244961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr) 298344961713Sgirish { 298444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 298544961713Sgirish struct ether_addr addrp; 298644961713Sgirish 298744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst")); 298844961713Sgirish 298944961713Sgirish bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 299044961713Sgirish if (nxge_set_mac_addr(nxgep, &addrp)) { 299144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 299244961713Sgirish "<== nxge_m_unicst: set unitcast failed")); 299344961713Sgirish return (EINVAL); 299444961713Sgirish } 299544961713Sgirish 299644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst")); 299744961713Sgirish 299844961713Sgirish return (0); 299944961713Sgirish } 300044961713Sgirish 300144961713Sgirish static int 300244961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 300344961713Sgirish { 300444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 300544961713Sgirish struct ether_addr addrp; 300644961713Sgirish 300744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 300844961713Sgirish "==> nxge_m_multicst: add %d", add)); 300944961713Sgirish 301044961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 301144961713Sgirish if (add) { 301244961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 301344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 301444961713Sgirish "<== nxge_m_multicst: add multicast failed")); 301544961713Sgirish return (EINVAL); 301644961713Sgirish } 301744961713Sgirish } else { 301844961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 301944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 302044961713Sgirish "<== nxge_m_multicst: del multicast failed")); 302144961713Sgirish return (EINVAL); 302244961713Sgirish } 302344961713Sgirish } 302444961713Sgirish 302544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 302644961713Sgirish 302744961713Sgirish return (0); 302844961713Sgirish } 302944961713Sgirish 303044961713Sgirish static int 303144961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 303244961713Sgirish { 303344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 303444961713Sgirish 303544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 303644961713Sgirish "==> nxge_m_promisc: on %d", on)); 303744961713Sgirish 303844961713Sgirish if (nxge_set_promisc(nxgep, on)) { 303944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 304044961713Sgirish "<== nxge_m_promisc: set promisc failed")); 304144961713Sgirish return (EINVAL); 304244961713Sgirish } 304344961713Sgirish 304444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 304544961713Sgirish "<== nxge_m_promisc: on %d", on)); 304644961713Sgirish 304744961713Sgirish return (0); 304844961713Sgirish } 304944961713Sgirish 305044961713Sgirish static void 305144961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 305244961713Sgirish { 305344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 305444961713Sgirish struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 305544961713Sgirish boolean_t need_privilege; 305644961713Sgirish int err; 305744961713Sgirish int cmd; 305844961713Sgirish 305944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 306044961713Sgirish 306144961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 306244961713Sgirish iocp->ioc_error = 0; 306344961713Sgirish need_privilege = B_TRUE; 306444961713Sgirish cmd = iocp->ioc_cmd; 306544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 306644961713Sgirish switch (cmd) { 306744961713Sgirish default: 306844961713Sgirish miocnak(wq, mp, 0, EINVAL); 306944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 307044961713Sgirish return; 307144961713Sgirish 307244961713Sgirish case LB_GET_INFO_SIZE: 307344961713Sgirish case LB_GET_INFO: 307444961713Sgirish case LB_GET_MODE: 307544961713Sgirish need_privilege = B_FALSE; 307644961713Sgirish break; 307744961713Sgirish case LB_SET_MODE: 307844961713Sgirish break; 307944961713Sgirish 308044961713Sgirish case ND_GET: 308144961713Sgirish need_privilege = B_FALSE; 308244961713Sgirish break; 308344961713Sgirish case ND_SET: 308444961713Sgirish break; 308544961713Sgirish 308644961713Sgirish case NXGE_GET_MII: 308744961713Sgirish case NXGE_PUT_MII: 308844961713Sgirish case NXGE_GET64: 308944961713Sgirish case NXGE_PUT64: 309044961713Sgirish case NXGE_GET_TX_RING_SZ: 309144961713Sgirish case NXGE_GET_TX_DESC: 309244961713Sgirish case NXGE_TX_SIDE_RESET: 309344961713Sgirish case NXGE_RX_SIDE_RESET: 309444961713Sgirish case NXGE_GLOBAL_RESET: 309544961713Sgirish case NXGE_RESET_MAC: 309644961713Sgirish case NXGE_TX_REGS_DUMP: 309744961713Sgirish case NXGE_RX_REGS_DUMP: 309844961713Sgirish case NXGE_INT_REGS_DUMP: 309944961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 310044961713Sgirish case NXGE_PUT_TCAM: 310144961713Sgirish case NXGE_GET_TCAM: 310244961713Sgirish case NXGE_RTRACE: 310344961713Sgirish case NXGE_RDUMP: 310444961713Sgirish 310544961713Sgirish need_privilege = B_FALSE; 310644961713Sgirish break; 310744961713Sgirish case NXGE_INJECT_ERR: 310844961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 310944961713Sgirish nxge_err_inject(nxgep, wq, mp); 311044961713Sgirish break; 311144961713Sgirish } 311244961713Sgirish 311344961713Sgirish if (need_privilege) { 311444961713Sgirish if (secpolicy_net_config != NULL) 311544961713Sgirish err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 311644961713Sgirish else 311744961713Sgirish err = drv_priv(iocp->ioc_cr); 311844961713Sgirish if (err != 0) { 311944961713Sgirish miocnak(wq, mp, 0, err); 312044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 312144961713Sgirish "<== nxge_m_ioctl: no priv")); 312244961713Sgirish return; 312344961713Sgirish } 312444961713Sgirish } 312544961713Sgirish 312644961713Sgirish switch (cmd) { 312744961713Sgirish case ND_GET: 312844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_GET command")); 312944961713Sgirish case ND_SET: 313044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_SET command")); 313144961713Sgirish nxge_param_ioctl(nxgep, wq, mp, iocp); 313244961713Sgirish break; 313344961713Sgirish 313444961713Sgirish case LB_GET_MODE: 313544961713Sgirish case LB_SET_MODE: 313644961713Sgirish case LB_GET_INFO_SIZE: 313744961713Sgirish case LB_GET_INFO: 313844961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 313944961713Sgirish break; 314044961713Sgirish 314144961713Sgirish case NXGE_GET_MII: 314244961713Sgirish case NXGE_PUT_MII: 314344961713Sgirish case NXGE_PUT_TCAM: 314444961713Sgirish case NXGE_GET_TCAM: 314544961713Sgirish case NXGE_GET64: 314644961713Sgirish case NXGE_PUT64: 314744961713Sgirish case NXGE_GET_TX_RING_SZ: 314844961713Sgirish case NXGE_GET_TX_DESC: 314944961713Sgirish case NXGE_TX_SIDE_RESET: 315044961713Sgirish case NXGE_RX_SIDE_RESET: 315144961713Sgirish case NXGE_GLOBAL_RESET: 315244961713Sgirish case NXGE_RESET_MAC: 315344961713Sgirish case NXGE_TX_REGS_DUMP: 315444961713Sgirish case NXGE_RX_REGS_DUMP: 315544961713Sgirish case NXGE_INT_REGS_DUMP: 315644961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 315744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 315844961713Sgirish "==> nxge_m_ioctl: cmd 0x%x", cmd)); 315944961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 316044961713Sgirish break; 316144961713Sgirish } 316244961713Sgirish 316344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 316444961713Sgirish } 316544961713Sgirish 316644961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 316744961713Sgirish 316844961713Sgirish static void 316944961713Sgirish nxge_m_resources(void *arg) 317044961713Sgirish { 317144961713Sgirish p_nxge_t nxgep = arg; 317244961713Sgirish mac_rx_fifo_t mrf; 317344961713Sgirish p_rx_rcr_rings_t rcr_rings; 317444961713Sgirish p_rx_rcr_ring_t *rcr_p; 317544961713Sgirish uint32_t i, ndmas; 317614ea4bb7Ssd nxge_status_t status; 317744961713Sgirish 317844961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources")); 317944961713Sgirish 318044961713Sgirish MUTEX_ENTER(nxgep->genlock); 318114ea4bb7Ssd 318214ea4bb7Ssd /* 318358324dfcSspeer * CR 6492541 Check to see if the drv_state has been initialized, 318414ea4bb7Ssd * if not * call nxge_init(). 318514ea4bb7Ssd */ 318614ea4bb7Ssd if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 318714ea4bb7Ssd status = nxge_init(nxgep); 318814ea4bb7Ssd if (status != NXGE_OK) 318914ea4bb7Ssd goto nxge_m_resources_exit; 319014ea4bb7Ssd } 319114ea4bb7Ssd 319244961713Sgirish mrf.mrf_type = MAC_RX_FIFO; 319344961713Sgirish mrf.mrf_blank = nxge_rx_hw_blank; 319444961713Sgirish mrf.mrf_arg = (void *)nxgep; 319544961713Sgirish 319644961713Sgirish mrf.mrf_normal_blank_time = 128; 319744961713Sgirish mrf.mrf_normal_pkt_count = 8; 319844961713Sgirish rcr_rings = nxgep->rx_rcr_rings; 319944961713Sgirish rcr_p = rcr_rings->rcr_rings; 320044961713Sgirish ndmas = rcr_rings->ndmas; 320144961713Sgirish 320214ea4bb7Ssd /* 320314ea4bb7Ssd * Export our receive resources to the MAC layer. 320414ea4bb7Ssd */ 320544961713Sgirish for (i = 0; i < ndmas; i++) { 320644961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle = 320744961713Sgirish mac_resource_add(nxgep->mach, 320844961713Sgirish (mac_resource_t *)&mrf); 320944961713Sgirish 321044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 321144961713Sgirish "==> nxge_m_resources: vdma %d dma %d " 321244961713Sgirish "rcrptr 0x%016llx mac_handle 0x%016llx", 321344961713Sgirish i, ((p_rx_rcr_ring_t)rcr_p[i])->rdc, 321444961713Sgirish rcr_p[i], 321544961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle)); 321644961713Sgirish } 321744961713Sgirish 321814ea4bb7Ssd nxge_m_resources_exit: 321944961713Sgirish MUTEX_EXIT(nxgep->genlock); 322044961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources")); 322144961713Sgirish } 322244961713Sgirish 322358324dfcSspeer static void 322458324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory) 322558324dfcSspeer { 322658324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 322758324dfcSspeer int i; 322858324dfcSspeer nxge_mmac_t *mmac_info; 322958324dfcSspeer 323058324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 323158324dfcSspeer 323258324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 323358324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 323458324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 323558324dfcSspeer 323658324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 323758324dfcSspeer if (factory) { 323858324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 323958324dfcSspeer = mmac_info->factory_mac_pool[slot][(ETHERADDRL-1) - i]; 324058324dfcSspeer } else { 324158324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 324258324dfcSspeer = mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i]; 324358324dfcSspeer } 324458324dfcSspeer } 324558324dfcSspeer } 324658324dfcSspeer 324758324dfcSspeer /* 324858324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 324958324dfcSspeer */ 325058324dfcSspeer static int 325158324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot) 325258324dfcSspeer { 325358324dfcSspeer uint8_t addrn; 325458324dfcSspeer uint8_t portn; 325558324dfcSspeer npi_mac_addr_t altmac; 325658324dfcSspeer 325758324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 325858324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 325958324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 326058324dfcSspeer 326158324dfcSspeer portn = nxgep->mac.portnum; 326258324dfcSspeer addrn = (uint8_t)slot - 1; 326358324dfcSspeer 326458324dfcSspeer if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn, 326558324dfcSspeer addrn, &altmac) != NPI_SUCCESS) 326658324dfcSspeer return (EIO); 326758324dfcSspeer /* 326858324dfcSspeer * Enable comparison with the alternate MAC address. 326958324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 327058324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 327158324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 327258324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 327358324dfcSspeer */ 327458324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 327558324dfcSspeer addrn = (uint8_t)slot - 1; 327658324dfcSspeer else 327758324dfcSspeer addrn = (uint8_t)slot; 327858324dfcSspeer 327958324dfcSspeer if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn) 328058324dfcSspeer != NPI_SUCCESS) 328158324dfcSspeer return (EIO); 328258324dfcSspeer 328358324dfcSspeer return (0); 328458324dfcSspeer } 328558324dfcSspeer 328658324dfcSspeer /* 328758324dfcSspeer * nxeg_m_mmac_add() - find an unused address slot, set the address 328858324dfcSspeer * value to the one specified, enable the port to start filtering on 328958324dfcSspeer * the new MAC address. Returns 0 on success. 329058324dfcSspeer */ 329158324dfcSspeer static int 329258324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 329358324dfcSspeer { 329458324dfcSspeer p_nxge_t nxgep = arg; 329558324dfcSspeer mac_addr_slot_t slot; 329658324dfcSspeer nxge_mmac_t *mmac_info; 329758324dfcSspeer int err; 329858324dfcSspeer nxge_status_t status; 329958324dfcSspeer 330058324dfcSspeer mutex_enter(nxgep->genlock); 330158324dfcSspeer 330258324dfcSspeer /* 330358324dfcSspeer * Make sure that nxge is initialized, if _start() has 330458324dfcSspeer * not been called. 330558324dfcSspeer */ 330658324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 330758324dfcSspeer status = nxge_init(nxgep); 330858324dfcSspeer if (status != NXGE_OK) { 330958324dfcSspeer mutex_exit(nxgep->genlock); 331058324dfcSspeer return (ENXIO); 331158324dfcSspeer } 331258324dfcSspeer } 331358324dfcSspeer 331458324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 331558324dfcSspeer if (mmac_info->naddrfree == 0) { 331658324dfcSspeer mutex_exit(nxgep->genlock); 331758324dfcSspeer return (ENOSPC); 331858324dfcSspeer } 331958324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 332058324dfcSspeer maddr->mma_addrlen)) { 332158324dfcSspeer mutex_exit(nxgep->genlock); 332258324dfcSspeer return (EINVAL); 332358324dfcSspeer } 332458324dfcSspeer /* 332558324dfcSspeer * Search for the first available slot. Because naddrfree 332658324dfcSspeer * is not zero, we are guaranteed to find one. 332758324dfcSspeer * Slot 0 is for unique (primary) MAC. The first alternate 332858324dfcSspeer * MAC slot is slot 1. 332958324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 333058324dfcSspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 333158324dfcSspeer * MAC addresses. We first search among the slots without bundled 333258324dfcSspeer * factory MACs. If we fail to find one in that range, then we 333358324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 333458324dfcSspeer * will be wasted while the slot is used with a user MAC address. 333558324dfcSspeer * But the slot could be used by factory MAC again after calling 333658324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 333758324dfcSspeer */ 333858324dfcSspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 333958324dfcSspeer for (slot = mmac_info->num_factory_mmac + 1; 334058324dfcSspeer slot <= mmac_info->num_mmac; slot++) { 334158324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 334258324dfcSspeer break; 334358324dfcSspeer } 334458324dfcSspeer if (slot > mmac_info->num_mmac) { 334558324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 334658324dfcSspeer slot++) { 334758324dfcSspeer if (!(mmac_info->mac_pool[slot].flags 334858324dfcSspeer & MMAC_SLOT_USED)) 334958324dfcSspeer break; 335058324dfcSspeer } 335158324dfcSspeer } 335258324dfcSspeer } else { 335358324dfcSspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 335458324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 335558324dfcSspeer break; 335658324dfcSspeer } 335758324dfcSspeer } 335858324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 335958324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) { 336058324dfcSspeer mutex_exit(nxgep->genlock); 336158324dfcSspeer return (err); 336258324dfcSspeer } 336358324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 336458324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 336558324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 336658324dfcSspeer mmac_info->naddrfree--; 336758324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 336858324dfcSspeer 336958324dfcSspeer maddr->mma_slot = slot; 337058324dfcSspeer 337158324dfcSspeer mutex_exit(nxgep->genlock); 337258324dfcSspeer return (0); 337358324dfcSspeer } 337458324dfcSspeer 337558324dfcSspeer /* 337658324dfcSspeer * This function reserves an unused slot and programs the slot and the HW 337758324dfcSspeer * with a factory mac address. 337858324dfcSspeer */ 337958324dfcSspeer static int 338058324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr) 338158324dfcSspeer { 338258324dfcSspeer p_nxge_t nxgep = arg; 338358324dfcSspeer mac_addr_slot_t slot; 338458324dfcSspeer nxge_mmac_t *mmac_info; 338558324dfcSspeer int err; 338658324dfcSspeer nxge_status_t status; 338758324dfcSspeer 338858324dfcSspeer mutex_enter(nxgep->genlock); 338958324dfcSspeer 339058324dfcSspeer /* 339158324dfcSspeer * Make sure that nxge is initialized, if _start() has 339258324dfcSspeer * not been called. 339358324dfcSspeer */ 339458324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 339558324dfcSspeer status = nxge_init(nxgep); 339658324dfcSspeer if (status != NXGE_OK) { 339758324dfcSspeer mutex_exit(nxgep->genlock); 339858324dfcSspeer return (ENXIO); 339958324dfcSspeer } 340058324dfcSspeer } 340158324dfcSspeer 340258324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 340358324dfcSspeer if (mmac_info->naddrfree == 0) { 340458324dfcSspeer mutex_exit(nxgep->genlock); 340558324dfcSspeer return (ENOSPC); 340658324dfcSspeer } 340758324dfcSspeer 340858324dfcSspeer slot = maddr->mma_slot; 340958324dfcSspeer if (slot == -1) { /* -1: Take the first available slot */ 341058324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) { 341158324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 341258324dfcSspeer break; 341358324dfcSspeer } 341458324dfcSspeer if (slot > mmac_info->num_factory_mmac) { 341558324dfcSspeer mutex_exit(nxgep->genlock); 341658324dfcSspeer return (ENOSPC); 341758324dfcSspeer } 341858324dfcSspeer } 341958324dfcSspeer if (slot < 1 || slot > mmac_info->num_factory_mmac) { 342058324dfcSspeer /* 342158324dfcSspeer * Do not support factory MAC at a slot greater than 342258324dfcSspeer * num_factory_mmac even when there are available factory 342358324dfcSspeer * MAC addresses because the alternate MACs are bundled with 342458324dfcSspeer * slot[1] through slot[num_factory_mmac] 342558324dfcSspeer */ 342658324dfcSspeer mutex_exit(nxgep->genlock); 342758324dfcSspeer return (EINVAL); 342858324dfcSspeer } 342958324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 343058324dfcSspeer mutex_exit(nxgep->genlock); 343158324dfcSspeer return (EBUSY); 343258324dfcSspeer } 343358324dfcSspeer /* Verify the address to be reserved */ 343458324dfcSspeer if (!mac_unicst_verify(nxgep->mach, 343558324dfcSspeer mmac_info->factory_mac_pool[slot], ETHERADDRL)) { 343658324dfcSspeer mutex_exit(nxgep->genlock); 343758324dfcSspeer return (EINVAL); 343858324dfcSspeer } 343958324dfcSspeer if (err = nxge_altmac_set(nxgep, 344058324dfcSspeer mmac_info->factory_mac_pool[slot], slot)) { 344158324dfcSspeer mutex_exit(nxgep->genlock); 344258324dfcSspeer return (err); 344358324dfcSspeer } 344458324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL); 344558324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 344658324dfcSspeer mmac_info->naddrfree--; 344758324dfcSspeer 344858324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_TRUE); 344958324dfcSspeer mutex_exit(nxgep->genlock); 345058324dfcSspeer 345158324dfcSspeer /* Pass info back to the caller */ 345258324dfcSspeer maddr->mma_slot = slot; 345358324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 345458324dfcSspeer maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 345558324dfcSspeer 345658324dfcSspeer return (0); 345758324dfcSspeer } 345858324dfcSspeer 345958324dfcSspeer /* 346058324dfcSspeer * Remove the specified mac address and update the HW not to filter 346158324dfcSspeer * the mac address anymore. 346258324dfcSspeer */ 346358324dfcSspeer static int 346458324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 346558324dfcSspeer { 346658324dfcSspeer p_nxge_t nxgep = arg; 346758324dfcSspeer nxge_mmac_t *mmac_info; 346858324dfcSspeer uint8_t addrn; 346958324dfcSspeer uint8_t portn; 347058324dfcSspeer int err = 0; 347158324dfcSspeer nxge_status_t status; 347258324dfcSspeer 347358324dfcSspeer mutex_enter(nxgep->genlock); 347458324dfcSspeer 347558324dfcSspeer /* 347658324dfcSspeer * Make sure that nxge is initialized, if _start() has 347758324dfcSspeer * not been called. 347858324dfcSspeer */ 347958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 348058324dfcSspeer status = nxge_init(nxgep); 348158324dfcSspeer if (status != NXGE_OK) { 348258324dfcSspeer mutex_exit(nxgep->genlock); 348358324dfcSspeer return (ENXIO); 348458324dfcSspeer } 348558324dfcSspeer } 348658324dfcSspeer 348758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 348858324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 348958324dfcSspeer mutex_exit(nxgep->genlock); 349058324dfcSspeer return (EINVAL); 349158324dfcSspeer } 349258324dfcSspeer 349358324dfcSspeer portn = nxgep->mac.portnum; 349458324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 349558324dfcSspeer addrn = (uint8_t)slot - 1; 349658324dfcSspeer else 349758324dfcSspeer addrn = (uint8_t)slot; 349858324dfcSspeer 349958324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 350058324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 350158324dfcSspeer == NPI_SUCCESS) { 350258324dfcSspeer mmac_info->naddrfree++; 350358324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 350458324dfcSspeer /* 350558324dfcSspeer * Regardless if the MAC we just stopped filtering 350658324dfcSspeer * is a user addr or a facory addr, we must set 350758324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 350858324dfcSspeer * associated factory MAC to indicate that a factory 350958324dfcSspeer * MAC is available. 351058324dfcSspeer */ 351158324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 351258324dfcSspeer mmac_info->mac_pool[slot].flags 351358324dfcSspeer |= MMAC_VENDOR_ADDR; 351458324dfcSspeer } 351558324dfcSspeer /* 351658324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 351758324dfcSspeer * alternate MAC address if the slot is not used. 351858324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 351958324dfcSspeer * when the slot is not used!) 352058324dfcSspeer */ 352158324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 352258324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 352358324dfcSspeer } else { 352458324dfcSspeer err = EIO; 352558324dfcSspeer } 352658324dfcSspeer } else { 352758324dfcSspeer err = EINVAL; 352858324dfcSspeer } 352958324dfcSspeer 353058324dfcSspeer mutex_exit(nxgep->genlock); 353158324dfcSspeer return (err); 353258324dfcSspeer } 353358324dfcSspeer 353458324dfcSspeer 353558324dfcSspeer /* 353658324dfcSspeer * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve(). 353758324dfcSspeer */ 353858324dfcSspeer static int 353958324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 354058324dfcSspeer { 354158324dfcSspeer p_nxge_t nxgep = arg; 354258324dfcSspeer mac_addr_slot_t slot; 354358324dfcSspeer nxge_mmac_t *mmac_info; 354458324dfcSspeer int err = 0; 354558324dfcSspeer nxge_status_t status; 354658324dfcSspeer 354758324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 354858324dfcSspeer maddr->mma_addrlen)) 354958324dfcSspeer return (EINVAL); 355058324dfcSspeer 355158324dfcSspeer slot = maddr->mma_slot; 355258324dfcSspeer 355358324dfcSspeer mutex_enter(nxgep->genlock); 355458324dfcSspeer 355558324dfcSspeer /* 355658324dfcSspeer * Make sure that nxge is initialized, if _start() has 355758324dfcSspeer * not been called. 355858324dfcSspeer */ 355958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 356058324dfcSspeer status = nxge_init(nxgep); 356158324dfcSspeer if (status != NXGE_OK) { 356258324dfcSspeer mutex_exit(nxgep->genlock); 356358324dfcSspeer return (ENXIO); 356458324dfcSspeer } 356558324dfcSspeer } 356658324dfcSspeer 356758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 356858324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 356958324dfcSspeer mutex_exit(nxgep->genlock); 357058324dfcSspeer return (EINVAL); 357158324dfcSspeer } 357258324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 357358324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) 357458324dfcSspeer != 0) { 357558324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 357658324dfcSspeer ETHERADDRL); 357758324dfcSspeer /* 357858324dfcSspeer * Assume that the MAC passed down from the caller 357958324dfcSspeer * is not a factory MAC address (The user should 358058324dfcSspeer * call mmac_remove followed by mmac_reserve if 358158324dfcSspeer * he wants to use the factory MAC for this slot). 358258324dfcSspeer */ 358358324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 358458324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 358558324dfcSspeer } 358658324dfcSspeer } else { 358758324dfcSspeer err = EINVAL; 358858324dfcSspeer } 358958324dfcSspeer mutex_exit(nxgep->genlock); 359058324dfcSspeer return (err); 359158324dfcSspeer } 359258324dfcSspeer 359358324dfcSspeer /* 359458324dfcSspeer * nxge_m_mmac_get() - Get the MAC address and other information 359558324dfcSspeer * related to the slot. mma_flags should be set to 0 in the call. 359658324dfcSspeer * Note: although kstat shows MAC address as zero when a slot is 359758324dfcSspeer * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC 359858324dfcSspeer * to the caller as long as the slot is not using a user MAC address. 359958324dfcSspeer * The following table shows the rules, 360058324dfcSspeer * 360158324dfcSspeer * USED VENDOR mma_addr 360258324dfcSspeer * ------------------------------------------------------------ 360358324dfcSspeer * (1) Slot uses a user MAC: yes no user MAC 360458324dfcSspeer * (2) Slot uses a factory MAC: yes yes factory MAC 360558324dfcSspeer * (3) Slot is not used but is 360658324dfcSspeer * factory MAC capable: no yes factory MAC 360758324dfcSspeer * (4) Slot is not used and is 360858324dfcSspeer * not factory MAC capable: no no 0 360958324dfcSspeer * ------------------------------------------------------------ 361058324dfcSspeer */ 361158324dfcSspeer static int 361258324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 361358324dfcSspeer { 361458324dfcSspeer nxge_t *nxgep = arg; 361558324dfcSspeer mac_addr_slot_t slot; 361658324dfcSspeer nxge_mmac_t *mmac_info; 361758324dfcSspeer nxge_status_t status; 361858324dfcSspeer 361958324dfcSspeer slot = maddr->mma_slot; 362058324dfcSspeer 362158324dfcSspeer mutex_enter(nxgep->genlock); 362258324dfcSspeer 362358324dfcSspeer /* 362458324dfcSspeer * Make sure that nxge is initialized, if _start() has 362558324dfcSspeer * not been called. 362658324dfcSspeer */ 362758324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 362858324dfcSspeer status = nxge_init(nxgep); 362958324dfcSspeer if (status != NXGE_OK) { 363058324dfcSspeer mutex_exit(nxgep->genlock); 363158324dfcSspeer return (ENXIO); 363258324dfcSspeer } 363358324dfcSspeer } 363458324dfcSspeer 363558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 363658324dfcSspeer 363758324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 363858324dfcSspeer mutex_exit(nxgep->genlock); 363958324dfcSspeer return (EINVAL); 364058324dfcSspeer } 364158324dfcSspeer maddr->mma_flags = 0; 364258324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) 364358324dfcSspeer maddr->mma_flags |= MMAC_SLOT_USED; 364458324dfcSspeer 364558324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) { 364658324dfcSspeer maddr->mma_flags |= MMAC_VENDOR_ADDR; 364758324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], 364858324dfcSspeer maddr->mma_addr, ETHERADDRL); 364958324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 365058324dfcSspeer } else { 365158324dfcSspeer if (maddr->mma_flags & MMAC_SLOT_USED) { 365258324dfcSspeer bcopy(mmac_info->mac_pool[slot].addr, 365358324dfcSspeer maddr->mma_addr, ETHERADDRL); 365458324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 365558324dfcSspeer } else { 365658324dfcSspeer bzero(maddr->mma_addr, ETHERADDRL); 365758324dfcSspeer maddr->mma_addrlen = 0; 365858324dfcSspeer } 365958324dfcSspeer } 366058324dfcSspeer mutex_exit(nxgep->genlock); 366158324dfcSspeer return (0); 366258324dfcSspeer } 366358324dfcSspeer 366458324dfcSspeer 366544961713Sgirish static boolean_t 366644961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 366744961713Sgirish { 366858324dfcSspeer nxge_t *nxgep = arg; 366958324dfcSspeer uint32_t *txflags = cap_data; 367058324dfcSspeer multiaddress_capab_t *mmacp = cap_data; 367144961713Sgirish 367258324dfcSspeer switch (cap) { 367358324dfcSspeer case MAC_CAPAB_HCKSUM: 367444961713Sgirish *txflags = HCKSUM_INET_PARTIAL; 367544961713Sgirish break; 367644961713Sgirish case MAC_CAPAB_POLL: 367744961713Sgirish /* 367844961713Sgirish * There's nothing for us to fill in, simply returning 367944961713Sgirish * B_TRUE stating that we support polling is sufficient. 368044961713Sgirish */ 368144961713Sgirish break; 368244961713Sgirish 368358324dfcSspeer case MAC_CAPAB_MULTIADDRESS: 368458324dfcSspeer mutex_enter(nxgep->genlock); 368558324dfcSspeer 368658324dfcSspeer mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac; 368758324dfcSspeer mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree; 368858324dfcSspeer mmacp->maddr_flag = 0; /* 0 is requried by PSARC2006/265 */ 368958324dfcSspeer /* 369058324dfcSspeer * maddr_handle is driver's private data, passed back to 369158324dfcSspeer * entry point functions as arg. 369258324dfcSspeer */ 369358324dfcSspeer mmacp->maddr_handle = nxgep; 369458324dfcSspeer mmacp->maddr_add = nxge_m_mmac_add; 369558324dfcSspeer mmacp->maddr_remove = nxge_m_mmac_remove; 369658324dfcSspeer mmacp->maddr_modify = nxge_m_mmac_modify; 369758324dfcSspeer mmacp->maddr_get = nxge_m_mmac_get; 369858324dfcSspeer mmacp->maddr_reserve = nxge_m_mmac_reserve; 369958324dfcSspeer 370058324dfcSspeer mutex_exit(nxgep->genlock); 370158324dfcSspeer break; 370244961713Sgirish default: 370344961713Sgirish return (B_FALSE); 370444961713Sgirish } 370544961713Sgirish return (B_TRUE); 370644961713Sgirish } 370744961713Sgirish 370844961713Sgirish /* 370944961713Sgirish * Module loading and removing entry points. 371044961713Sgirish */ 371144961713Sgirish 371244961713Sgirish static struct cb_ops nxge_cb_ops = { 371344961713Sgirish nodev, /* cb_open */ 371444961713Sgirish nodev, /* cb_close */ 371544961713Sgirish nodev, /* cb_strategy */ 371644961713Sgirish nodev, /* cb_print */ 371744961713Sgirish nodev, /* cb_dump */ 371844961713Sgirish nodev, /* cb_read */ 371944961713Sgirish nodev, /* cb_write */ 372044961713Sgirish nodev, /* cb_ioctl */ 372144961713Sgirish nodev, /* cb_devmap */ 372244961713Sgirish nodev, /* cb_mmap */ 372344961713Sgirish nodev, /* cb_segmap */ 372444961713Sgirish nochpoll, /* cb_chpoll */ 372544961713Sgirish ddi_prop_op, /* cb_prop_op */ 372644961713Sgirish NULL, 372744961713Sgirish D_MP, /* cb_flag */ 372844961713Sgirish CB_REV, /* rev */ 372944961713Sgirish nodev, /* int (*cb_aread)() */ 373044961713Sgirish nodev /* int (*cb_awrite)() */ 373144961713Sgirish }; 373244961713Sgirish 373344961713Sgirish static struct dev_ops nxge_dev_ops = { 373444961713Sgirish DEVO_REV, /* devo_rev */ 373544961713Sgirish 0, /* devo_refcnt */ 373644961713Sgirish nulldev, 373758324dfcSspeer nulldev, /* devo_identify */ 373858324dfcSspeer nulldev, /* devo_probe */ 373958324dfcSspeer nxge_attach, /* devo_attach */ 374058324dfcSspeer nxge_detach, /* devo_detach */ 374158324dfcSspeer nodev, /* devo_reset */ 374258324dfcSspeer &nxge_cb_ops, /* devo_cb_ops */ 374358324dfcSspeer (struct bus_ops *)NULL, /* devo_bus_ops */ 374458324dfcSspeer ddi_power /* devo_power */ 374544961713Sgirish }; 374644961713Sgirish 374744961713Sgirish extern struct mod_ops mod_driverops; 374844961713Sgirish 374944961713Sgirish #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet %I%" 375044961713Sgirish 375144961713Sgirish /* 375244961713Sgirish * Module linkage information for the kernel. 375344961713Sgirish */ 375444961713Sgirish static struct modldrv nxge_modldrv = { 375544961713Sgirish &mod_driverops, 375644961713Sgirish NXGE_DESC_VER, 375744961713Sgirish &nxge_dev_ops 375844961713Sgirish }; 375944961713Sgirish 376044961713Sgirish static struct modlinkage modlinkage = { 376144961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 376244961713Sgirish }; 376344961713Sgirish 376444961713Sgirish int 376544961713Sgirish _init(void) 376644961713Sgirish { 376744961713Sgirish int status; 376844961713Sgirish 376944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 377044961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 377144961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 377244961713Sgirish if (status != 0) { 377344961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 377444961713Sgirish "failed to init device soft state")); 377544961713Sgirish goto _init_exit; 377644961713Sgirish } 377744961713Sgirish 377844961713Sgirish status = mod_install(&modlinkage); 377944961713Sgirish if (status != 0) { 378044961713Sgirish ddi_soft_state_fini(&nxge_list); 378144961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 378244961713Sgirish goto _init_exit; 378344961713Sgirish } 378444961713Sgirish 378544961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 378644961713Sgirish 378744961713Sgirish _init_exit: 378844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 378944961713Sgirish 379044961713Sgirish return (status); 379144961713Sgirish } 379244961713Sgirish 379344961713Sgirish int 379444961713Sgirish _fini(void) 379544961713Sgirish { 379644961713Sgirish int status; 379744961713Sgirish 379844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 379944961713Sgirish 380044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 3801a3c5bd6dSspeer 3802a3c5bd6dSspeer if (nxge_mblks_pending) 3803a3c5bd6dSspeer return (EBUSY); 3804a3c5bd6dSspeer 380544961713Sgirish status = mod_remove(&modlinkage); 380644961713Sgirish if (status != DDI_SUCCESS) { 380744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 380844961713Sgirish "Module removal failed 0x%08x", 380944961713Sgirish status)); 381044961713Sgirish goto _fini_exit; 381144961713Sgirish } 381244961713Sgirish 381344961713Sgirish mac_fini_ops(&nxge_dev_ops); 381444961713Sgirish 381544961713Sgirish ddi_soft_state_fini(&nxge_list); 381644961713Sgirish 381744961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 381844961713Sgirish _fini_exit: 381944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 382044961713Sgirish 382144961713Sgirish return (status); 382244961713Sgirish } 382344961713Sgirish 382444961713Sgirish int 382544961713Sgirish _info(struct modinfo *modinfop) 382644961713Sgirish { 382744961713Sgirish int status; 382844961713Sgirish 382944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 383044961713Sgirish status = mod_info(&modlinkage, modinfop); 383144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 383244961713Sgirish 383344961713Sgirish return (status); 383444961713Sgirish } 383544961713Sgirish 383644961713Sgirish /*ARGSUSED*/ 383744961713Sgirish static nxge_status_t 383844961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 383944961713Sgirish { 384044961713Sgirish 384144961713Sgirish int intr_types; 384244961713Sgirish int type = 0; 384344961713Sgirish int ddi_status = DDI_SUCCESS; 384444961713Sgirish nxge_status_t status = NXGE_OK; 384544961713Sgirish 384644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 384744961713Sgirish 384844961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 384944961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 385044961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 385144961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 385244961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 385344961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 385444961713Sgirish 385544961713Sgirish if (nxgep->niu_type == N2_NIU) { 385644961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 385744961713Sgirish } else if (nxge_msi_enable) { 385844961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 385944961713Sgirish } 386044961713Sgirish 386144961713Sgirish /* Get the supported interrupt types */ 386244961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 386344961713Sgirish != DDI_SUCCESS) { 386444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 386544961713Sgirish "ddi_intr_get_supported_types failed: status 0x%08x", 386644961713Sgirish ddi_status)); 386744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 386844961713Sgirish } 386944961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 387044961713Sgirish 387144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 387244961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 387344961713Sgirish 387444961713Sgirish /* 387544961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 387644961713Sgirish * nxge_msi_enable (1): 387744961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 387844961713Sgirish */ 387944961713Sgirish switch (nxge_msi_enable) { 388044961713Sgirish default: 388144961713Sgirish type = DDI_INTR_TYPE_FIXED; 388244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 388344961713Sgirish "use fixed (intx emulation) type %08x", 388444961713Sgirish type)); 388544961713Sgirish break; 388644961713Sgirish 388744961713Sgirish case 2: 388844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 388944961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 389044961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 389144961713Sgirish type = DDI_INTR_TYPE_MSIX; 389244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 389344961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 389444961713Sgirish type)); 389544961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 389644961713Sgirish type = DDI_INTR_TYPE_MSI; 389744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 389844961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 389944961713Sgirish type)); 390044961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 390144961713Sgirish type = DDI_INTR_TYPE_FIXED; 390244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 390344961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 390444961713Sgirish type)); 390544961713Sgirish } 390644961713Sgirish break; 390744961713Sgirish 390844961713Sgirish case 1: 390944961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 391044961713Sgirish type = DDI_INTR_TYPE_MSI; 391144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 391244961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 391344961713Sgirish type)); 391444961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 391544961713Sgirish type = DDI_INTR_TYPE_MSIX; 391644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 391744961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 391844961713Sgirish type)); 391944961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 392044961713Sgirish type = DDI_INTR_TYPE_FIXED; 392144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 392244961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 392344961713Sgirish type)); 392444961713Sgirish } 392544961713Sgirish } 392644961713Sgirish 392744961713Sgirish nxgep->nxge_intr_type.intr_type = type; 392844961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 392944961713Sgirish type == DDI_INTR_TYPE_FIXED) && 393044961713Sgirish nxgep->nxge_intr_type.niu_msi_enable) { 393144961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 393244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 393344961713Sgirish " nxge_add_intrs: " 393444961713Sgirish " nxge_add_intrs_adv failed: status 0x%08x", 393544961713Sgirish status)); 393644961713Sgirish return (status); 393744961713Sgirish } else { 393844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 393944961713Sgirish "interrupts registered : type %d", type)); 394044961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 394144961713Sgirish 394244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 394344961713Sgirish "\nAdded advanced nxge add_intr_adv " 394444961713Sgirish "intr type 0x%x\n", type)); 394544961713Sgirish 394644961713Sgirish return (status); 394744961713Sgirish } 394844961713Sgirish } 394944961713Sgirish 395044961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 395144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 395244961713Sgirish "failed to register interrupts")); 395344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 395444961713Sgirish } 395544961713Sgirish 395644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 395744961713Sgirish return (status); 395844961713Sgirish } 395944961713Sgirish 396044961713Sgirish /*ARGSUSED*/ 396144961713Sgirish static nxge_status_t 396244961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep) 396344961713Sgirish { 396444961713Sgirish 396544961713Sgirish int ddi_status = DDI_SUCCESS; 396644961713Sgirish nxge_status_t status = NXGE_OK; 396744961713Sgirish 396844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs")); 396944961713Sgirish 397044961713Sgirish nxgep->resched_id = NULL; 397144961713Sgirish nxgep->resched_running = B_FALSE; 397244961713Sgirish ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW, 397344961713Sgirish &nxgep->resched_id, 397444961713Sgirish NULL, NULL, nxge_reschedule, (caddr_t)nxgep); 397544961713Sgirish if (ddi_status != DDI_SUCCESS) { 397644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: " 397744961713Sgirish "ddi_add_softintrs failed: status 0x%08x", 397844961713Sgirish ddi_status)); 397944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 398044961713Sgirish } 398144961713Sgirish 398244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs")); 398344961713Sgirish 398444961713Sgirish return (status); 398544961713Sgirish } 398644961713Sgirish 398744961713Sgirish static nxge_status_t 398844961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 398944961713Sgirish { 399044961713Sgirish int intr_type; 399144961713Sgirish p_nxge_intr_t intrp; 399244961713Sgirish 399344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 399444961713Sgirish 399544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 399644961713Sgirish intr_type = intrp->intr_type; 399744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 399844961713Sgirish intr_type)); 399944961713Sgirish 400044961713Sgirish switch (intr_type) { 400144961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 400244961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 400344961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 400444961713Sgirish 400544961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 400644961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 400744961713Sgirish 400844961713Sgirish default: 400944961713Sgirish return (NXGE_ERROR); 401044961713Sgirish } 401144961713Sgirish } 401244961713Sgirish 401344961713Sgirish 401444961713Sgirish /*ARGSUSED*/ 401544961713Sgirish static nxge_status_t 401644961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 401744961713Sgirish { 401844961713Sgirish dev_info_t *dip = nxgep->dip; 401944961713Sgirish p_nxge_ldg_t ldgp; 402044961713Sgirish p_nxge_intr_t intrp; 402144961713Sgirish uint_t *inthandler; 402244961713Sgirish void *arg1, *arg2; 402344961713Sgirish int behavior; 402444961713Sgirish int nintrs, navail; 402544961713Sgirish int nactual, nrequired; 402644961713Sgirish int inum = 0; 402744961713Sgirish int x, y; 402844961713Sgirish int ddi_status = DDI_SUCCESS; 402944961713Sgirish nxge_status_t status = NXGE_OK; 403044961713Sgirish 403144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 403244961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 403344961713Sgirish intrp->start_inum = 0; 403444961713Sgirish 403544961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 403644961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 403744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 403844961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 403944961713Sgirish "nintrs: %d", ddi_status, nintrs)); 404044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 404144961713Sgirish } 404244961713Sgirish 404344961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 404444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 404544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 404644961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 404744961713Sgirish "nintrs: %d", ddi_status, navail)); 404844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 404944961713Sgirish } 405044961713Sgirish 405144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 405244961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, navail %d", 405344961713Sgirish nintrs, navail)); 405444961713Sgirish 405544961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 405644961713Sgirish /* MSI must be power of 2 */ 405744961713Sgirish if ((navail & 16) == 16) { 405844961713Sgirish navail = 16; 405944961713Sgirish } else if ((navail & 8) == 8) { 406044961713Sgirish navail = 8; 406144961713Sgirish } else if ((navail & 4) == 4) { 406244961713Sgirish navail = 4; 406344961713Sgirish } else if ((navail & 2) == 2) { 406444961713Sgirish navail = 2; 406544961713Sgirish } else { 406644961713Sgirish navail = 1; 406744961713Sgirish } 406844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 406944961713Sgirish "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 407044961713Sgirish "navail %d", nintrs, navail)); 407144961713Sgirish } 407244961713Sgirish 407344961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 407444961713Sgirish DDI_INTR_ALLOC_NORMAL); 407544961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 407644961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 407744961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 407844961713Sgirish navail, &nactual, behavior); 407944961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 408044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 408144961713Sgirish " ddi_intr_alloc() failed: %d", 408244961713Sgirish ddi_status)); 408344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 408444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 408544961713Sgirish } 408644961713Sgirish 408744961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 408844961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 408944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 409044961713Sgirish " ddi_intr_get_pri() failed: %d", 409144961713Sgirish ddi_status)); 409244961713Sgirish /* Free already allocated interrupts */ 409344961713Sgirish for (y = 0; y < nactual; y++) { 409444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 409544961713Sgirish } 409644961713Sgirish 409744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 409844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 409944961713Sgirish } 410044961713Sgirish 410144961713Sgirish nrequired = 0; 410244961713Sgirish switch (nxgep->niu_type) { 410344961713Sgirish case NEPTUNE: 410444961713Sgirish case NEPTUNE_2: 410544961713Sgirish default: 410644961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 410744961713Sgirish break; 410844961713Sgirish 410944961713Sgirish case N2_NIU: 411044961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 411144961713Sgirish break; 411244961713Sgirish } 411344961713Sgirish 411444961713Sgirish if (status != NXGE_OK) { 411544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 411644961713Sgirish "nxge_add_intrs_adv_typ:nxge_ldgv_init " 411744961713Sgirish "failed: 0x%x", status)); 411844961713Sgirish /* Free already allocated interrupts */ 411944961713Sgirish for (y = 0; y < nactual; y++) { 412044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 412144961713Sgirish } 412244961713Sgirish 412344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 412444961713Sgirish return (status); 412544961713Sgirish } 412644961713Sgirish 412744961713Sgirish ldgp = nxgep->ldgvp->ldgp; 412844961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 412944961713Sgirish ldgp->vector = (uint8_t)x; 413044961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 413144961713Sgirish arg1 = ldgp->ldvp; 413244961713Sgirish arg2 = nxgep; 413344961713Sgirish if (ldgp->nldvs == 1) { 413444961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 413544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 413644961713Sgirish "nxge_add_intrs_adv_type: " 413744961713Sgirish "arg1 0x%x arg2 0x%x: " 413844961713Sgirish "1-1 int handler (entry %d intdata 0x%x)\n", 413944961713Sgirish arg1, arg2, 414044961713Sgirish x, ldgp->intdata)); 414144961713Sgirish } else if (ldgp->nldvs > 1) { 414244961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 414344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 414444961713Sgirish "nxge_add_intrs_adv_type: " 414544961713Sgirish "arg1 0x%x arg2 0x%x: " 414644961713Sgirish "nldevs %d int handler " 414744961713Sgirish "(entry %d intdata 0x%x)\n", 414844961713Sgirish arg1, arg2, 414944961713Sgirish ldgp->nldvs, x, ldgp->intdata)); 415044961713Sgirish } 415144961713Sgirish 415244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 415344961713Sgirish "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 415444961713Sgirish "htable 0x%llx", x, intrp->htable[x])); 415544961713Sgirish 415644961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 415744961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 415844961713Sgirish != DDI_SUCCESS) { 415944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 416044961713Sgirish "==> nxge_add_intrs_adv_type: failed #%d " 416144961713Sgirish "status 0x%x", x, ddi_status)); 416244961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 416344961713Sgirish (void) ddi_intr_remove_handler( 416444961713Sgirish intrp->htable[y]); 416544961713Sgirish } 416644961713Sgirish /* Free already allocated intr */ 416744961713Sgirish for (y = 0; y < nactual; y++) { 416844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 416944961713Sgirish } 417044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 417144961713Sgirish 417244961713Sgirish (void) nxge_ldgv_uninit(nxgep); 417344961713Sgirish 417444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 417544961713Sgirish } 417644961713Sgirish intrp->intr_added++; 417744961713Sgirish } 417844961713Sgirish 417944961713Sgirish intrp->msi_intx_cnt = nactual; 418044961713Sgirish 418144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 418244961713Sgirish "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 418344961713Sgirish navail, nactual, 418444961713Sgirish intrp->msi_intx_cnt, 418544961713Sgirish intrp->intr_added)); 418644961713Sgirish 418744961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 418844961713Sgirish 418944961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 419044961713Sgirish 419144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 419244961713Sgirish 419344961713Sgirish return (status); 419444961713Sgirish } 419544961713Sgirish 419644961713Sgirish /*ARGSUSED*/ 419744961713Sgirish static nxge_status_t 419844961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 419944961713Sgirish { 420044961713Sgirish dev_info_t *dip = nxgep->dip; 420144961713Sgirish p_nxge_ldg_t ldgp; 420244961713Sgirish p_nxge_intr_t intrp; 420344961713Sgirish uint_t *inthandler; 420444961713Sgirish void *arg1, *arg2; 420544961713Sgirish int behavior; 420644961713Sgirish int nintrs, navail; 420744961713Sgirish int nactual, nrequired; 420844961713Sgirish int inum = 0; 420944961713Sgirish int x, y; 421044961713Sgirish int ddi_status = DDI_SUCCESS; 421144961713Sgirish nxge_status_t status = NXGE_OK; 421244961713Sgirish 421344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 421444961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 421544961713Sgirish intrp->start_inum = 0; 421644961713Sgirish 421744961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 421844961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 421944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 422044961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 422144961713Sgirish "nintrs: %d", status, nintrs)); 422244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 422344961713Sgirish } 422444961713Sgirish 422544961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 422644961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 422744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 422844961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 422944961713Sgirish "nintrs: %d", ddi_status, navail)); 423044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 423144961713Sgirish } 423244961713Sgirish 423344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 423444961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 423544961713Sgirish nintrs, navail)); 423644961713Sgirish 423744961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 423844961713Sgirish DDI_INTR_ALLOC_NORMAL); 423944961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 424044961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 424144961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 424244961713Sgirish navail, &nactual, behavior); 424344961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 424444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 424544961713Sgirish " ddi_intr_alloc() failed: %d", 424644961713Sgirish ddi_status)); 424744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 424844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 424944961713Sgirish } 425044961713Sgirish 425144961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 425244961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 425344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 425444961713Sgirish " ddi_intr_get_pri() failed: %d", 425544961713Sgirish ddi_status)); 425644961713Sgirish /* Free already allocated interrupts */ 425744961713Sgirish for (y = 0; y < nactual; y++) { 425844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 425944961713Sgirish } 426044961713Sgirish 426144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 426244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 426344961713Sgirish } 426444961713Sgirish 426544961713Sgirish nrequired = 0; 426644961713Sgirish switch (nxgep->niu_type) { 426744961713Sgirish case NEPTUNE: 426844961713Sgirish case NEPTUNE_2: 426944961713Sgirish default: 427044961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 427144961713Sgirish break; 427244961713Sgirish 427344961713Sgirish case N2_NIU: 427444961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 427544961713Sgirish break; 427644961713Sgirish } 427744961713Sgirish 427844961713Sgirish if (status != NXGE_OK) { 427944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 428044961713Sgirish "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 428144961713Sgirish "failed: 0x%x", status)); 428244961713Sgirish /* Free already allocated interrupts */ 428344961713Sgirish for (y = 0; y < nactual; y++) { 428444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 428544961713Sgirish } 428644961713Sgirish 428744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 428844961713Sgirish return (status); 428944961713Sgirish } 429044961713Sgirish 429144961713Sgirish ldgp = nxgep->ldgvp->ldgp; 429244961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 429344961713Sgirish ldgp->vector = (uint8_t)x; 429444961713Sgirish if (nxgep->niu_type != N2_NIU) { 429544961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 429644961713Sgirish } 429744961713Sgirish 429844961713Sgirish arg1 = ldgp->ldvp; 429944961713Sgirish arg2 = nxgep; 430044961713Sgirish if (ldgp->nldvs == 1) { 430144961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 430244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 430344961713Sgirish "nxge_add_intrs_adv_type_fix: " 430444961713Sgirish "1-1 int handler(%d) ldg %d ldv %d " 430544961713Sgirish "arg1 $%p arg2 $%p\n", 430644961713Sgirish x, ldgp->ldg, ldgp->ldvp->ldv, 430744961713Sgirish arg1, arg2)); 430844961713Sgirish } else if (ldgp->nldvs > 1) { 430944961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 431044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 431144961713Sgirish "nxge_add_intrs_adv_type_fix: " 431244961713Sgirish "shared ldv %d int handler(%d) ldv %d ldg %d" 431344961713Sgirish "arg1 0x%016llx arg2 0x%016llx\n", 431444961713Sgirish x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 431544961713Sgirish arg1, arg2)); 431644961713Sgirish } 431744961713Sgirish 431844961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 431944961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 432044961713Sgirish != DDI_SUCCESS) { 432144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 432244961713Sgirish "==> nxge_add_intrs_adv_type_fix: failed #%d " 432344961713Sgirish "status 0x%x", x, ddi_status)); 432444961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 432544961713Sgirish (void) ddi_intr_remove_handler( 432644961713Sgirish intrp->htable[y]); 432744961713Sgirish } 432844961713Sgirish for (y = 0; y < nactual; y++) { 432944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 433044961713Sgirish } 433144961713Sgirish /* Free already allocated intr */ 433244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 433344961713Sgirish 433444961713Sgirish (void) nxge_ldgv_uninit(nxgep); 433544961713Sgirish 433644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 433744961713Sgirish } 433844961713Sgirish intrp->intr_added++; 433944961713Sgirish } 434044961713Sgirish 434144961713Sgirish intrp->msi_intx_cnt = nactual; 434244961713Sgirish 434344961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 434444961713Sgirish 434544961713Sgirish status = nxge_intr_ldgv_init(nxgep); 434644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 434744961713Sgirish 434844961713Sgirish return (status); 434944961713Sgirish } 435044961713Sgirish 435144961713Sgirish static void 435244961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 435344961713Sgirish { 435444961713Sgirish int i, inum; 435544961713Sgirish p_nxge_intr_t intrp; 435644961713Sgirish 435744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 435844961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 435944961713Sgirish if (!intrp->intr_registered) { 436044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 436144961713Sgirish "<== nxge_remove_intrs: interrupts not registered")); 436244961713Sgirish return; 436344961713Sgirish } 436444961713Sgirish 436544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 436644961713Sgirish 436744961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 436844961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 436944961713Sgirish intrp->intr_added); 437044961713Sgirish } else { 437144961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 437244961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 437344961713Sgirish } 437444961713Sgirish } 437544961713Sgirish 437644961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 437744961713Sgirish if (intrp->htable[inum]) { 437844961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 437944961713Sgirish } 438044961713Sgirish } 438144961713Sgirish 438244961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 438344961713Sgirish if (intrp->htable[inum]) { 438444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 438544961713Sgirish "nxge_remove_intrs: ddi_intr_free inum %d " 438644961713Sgirish "msi_intx_cnt %d intr_added %d", 438744961713Sgirish inum, 438844961713Sgirish intrp->msi_intx_cnt, 438944961713Sgirish intrp->intr_added)); 439044961713Sgirish 439144961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 439244961713Sgirish } 439344961713Sgirish } 439444961713Sgirish 439544961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 439644961713Sgirish intrp->intr_registered = B_FALSE; 439744961713Sgirish intrp->intr_enabled = B_FALSE; 439844961713Sgirish intrp->msi_intx_cnt = 0; 439944961713Sgirish intrp->intr_added = 0; 440044961713Sgirish 4401a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 4402a3c5bd6dSspeer 440344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 440444961713Sgirish } 440544961713Sgirish 440644961713Sgirish /*ARGSUSED*/ 440744961713Sgirish static void 440844961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep) 440944961713Sgirish { 441044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs")); 441144961713Sgirish if (nxgep->resched_id) { 441244961713Sgirish ddi_remove_softintr(nxgep->resched_id); 441344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 441444961713Sgirish "==> nxge_remove_soft_intrs: removed")); 441544961713Sgirish nxgep->resched_id = NULL; 441644961713Sgirish } 441744961713Sgirish 441844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs")); 441944961713Sgirish } 442044961713Sgirish 442144961713Sgirish /*ARGSUSED*/ 442244961713Sgirish static void 442344961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 442444961713Sgirish { 442544961713Sgirish p_nxge_intr_t intrp; 442644961713Sgirish int i; 442744961713Sgirish int status; 442844961713Sgirish 442944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 443044961713Sgirish 443144961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 443244961713Sgirish 443344961713Sgirish if (!intrp->intr_registered) { 443444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 443544961713Sgirish "interrupts are not registered")); 443644961713Sgirish return; 443744961713Sgirish } 443844961713Sgirish 443944961713Sgirish if (intrp->intr_enabled) { 444044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 444144961713Sgirish "<== nxge_intrs_enable: already enabled")); 444244961713Sgirish return; 444344961713Sgirish } 444444961713Sgirish 444544961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 444644961713Sgirish status = ddi_intr_block_enable(intrp->htable, 444744961713Sgirish intrp->intr_added); 444844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 444944961713Sgirish "block enable - status 0x%x total inums #%d\n", 445044961713Sgirish status, intrp->intr_added)); 445144961713Sgirish } else { 445244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 445344961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 445444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 445544961713Sgirish "ddi_intr_enable:enable - status 0x%x " 445644961713Sgirish "total inums %d enable inum #%d\n", 445744961713Sgirish status, intrp->intr_added, i)); 445844961713Sgirish if (status == DDI_SUCCESS) { 445944961713Sgirish intrp->intr_enabled = B_TRUE; 446044961713Sgirish } 446144961713Sgirish } 446244961713Sgirish } 446344961713Sgirish 446444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 446544961713Sgirish } 446644961713Sgirish 446744961713Sgirish /*ARGSUSED*/ 446844961713Sgirish static void 446944961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 447044961713Sgirish { 447144961713Sgirish p_nxge_intr_t intrp; 447244961713Sgirish int i; 447344961713Sgirish 447444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 447544961713Sgirish 447644961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 447744961713Sgirish 447844961713Sgirish if (!intrp->intr_registered) { 447944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 448044961713Sgirish "interrupts are not registered")); 448144961713Sgirish return; 448244961713Sgirish } 448344961713Sgirish 448444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 448544961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 448644961713Sgirish intrp->intr_added); 448744961713Sgirish } else { 448844961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 448944961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 449044961713Sgirish } 449144961713Sgirish } 449244961713Sgirish 449344961713Sgirish intrp->intr_enabled = B_FALSE; 449444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 449544961713Sgirish } 449644961713Sgirish 449744961713Sgirish static nxge_status_t 449844961713Sgirish nxge_mac_register(p_nxge_t nxgep) 449944961713Sgirish { 450044961713Sgirish mac_register_t *macp; 450144961713Sgirish int status; 450244961713Sgirish 450344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 450444961713Sgirish 450544961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 450644961713Sgirish return (NXGE_ERROR); 450744961713Sgirish 450844961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 450944961713Sgirish macp->m_driver = nxgep; 451044961713Sgirish macp->m_dip = nxgep->dip; 451144961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 451244961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 451344961713Sgirish macp->m_min_sdu = 0; 451444961713Sgirish macp->m_max_sdu = nxgep->mac.maxframesize - 451544961713Sgirish sizeof (struct ether_header) - ETHERFCSL - 4; 451644961713Sgirish 451744961713Sgirish status = mac_register(macp, &nxgep->mach); 451844961713Sgirish mac_free(macp); 451944961713Sgirish 452044961713Sgirish if (status != 0) { 452144961713Sgirish cmn_err(CE_WARN, 452244961713Sgirish "!nxge_mac_register failed (status %d instance %d)", 452344961713Sgirish status, nxgep->instance); 452444961713Sgirish return (NXGE_ERROR); 452544961713Sgirish } 452644961713Sgirish 452744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 452844961713Sgirish "(instance %d)", nxgep->instance)); 452944961713Sgirish 453044961713Sgirish return (NXGE_OK); 453144961713Sgirish } 453244961713Sgirish 453344961713Sgirish void 453444961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 453544961713Sgirish { 453644961713Sgirish ssize_t size; 453744961713Sgirish mblk_t *nmp; 453844961713Sgirish uint8_t blk_id; 453944961713Sgirish uint8_t chan; 454044961713Sgirish uint32_t err_id; 454144961713Sgirish err_inject_t *eip; 454244961713Sgirish 454344961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 454444961713Sgirish 454544961713Sgirish size = 1024; 454644961713Sgirish nmp = mp->b_cont; 454744961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 454844961713Sgirish blk_id = eip->blk_id; 454944961713Sgirish err_id = eip->err_id; 455044961713Sgirish chan = eip->chan; 455144961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 455244961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 455344961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 455444961713Sgirish switch (blk_id) { 455544961713Sgirish case MAC_BLK_ID: 455644961713Sgirish break; 455744961713Sgirish case TXMAC_BLK_ID: 455844961713Sgirish break; 455944961713Sgirish case RXMAC_BLK_ID: 456044961713Sgirish break; 456144961713Sgirish case MIF_BLK_ID: 456244961713Sgirish break; 456344961713Sgirish case IPP_BLK_ID: 456444961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 456544961713Sgirish break; 456644961713Sgirish case TXC_BLK_ID: 456744961713Sgirish nxge_txc_inject_err(nxgep, err_id); 456844961713Sgirish break; 456944961713Sgirish case TXDMA_BLK_ID: 457044961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 457144961713Sgirish break; 457244961713Sgirish case RXDMA_BLK_ID: 457344961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 457444961713Sgirish break; 457544961713Sgirish case ZCP_BLK_ID: 457644961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 457744961713Sgirish break; 457844961713Sgirish case ESPC_BLK_ID: 457944961713Sgirish break; 458044961713Sgirish case FFLP_BLK_ID: 458144961713Sgirish break; 458244961713Sgirish case PHY_BLK_ID: 458344961713Sgirish break; 458444961713Sgirish case ETHER_SERDES_BLK_ID: 458544961713Sgirish break; 458644961713Sgirish case PCIE_SERDES_BLK_ID: 458744961713Sgirish break; 458844961713Sgirish case VIR_BLK_ID: 458944961713Sgirish break; 459044961713Sgirish } 459144961713Sgirish 459244961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 459344961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 459444961713Sgirish 459544961713Sgirish miocack(wq, mp, (int)size, 0); 459644961713Sgirish } 459744961713Sgirish 459844961713Sgirish static int 459944961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 460044961713Sgirish { 460144961713Sgirish p_nxge_hw_list_t hw_p; 460244961713Sgirish dev_info_t *p_dip; 460344961713Sgirish 460444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 460544961713Sgirish 460644961713Sgirish p_dip = nxgep->p_dip; 460744961713Sgirish MUTEX_ENTER(&nxge_common_lock); 460844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 460944961713Sgirish "==> nxge_init_common_dev:func # %d", 461044961713Sgirish nxgep->function_num)); 461144961713Sgirish /* 461244961713Sgirish * Loop through existing per neptune hardware list. 461344961713Sgirish */ 461444961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 461544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 461644961713Sgirish "==> nxge_init_common_device:func # %d " 461744961713Sgirish "hw_p $%p parent dip $%p", 461844961713Sgirish nxgep->function_num, 461944961713Sgirish hw_p, 462044961713Sgirish p_dip)); 462144961713Sgirish if (hw_p->parent_devp == p_dip) { 462244961713Sgirish nxgep->nxge_hw_p = hw_p; 462344961713Sgirish hw_p->ndevs++; 462444961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 462544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 462644961713Sgirish "==> nxge_init_common_device:func # %d " 462744961713Sgirish "hw_p $%p parent dip $%p " 462844961713Sgirish "ndevs %d (found)", 462944961713Sgirish nxgep->function_num, 463044961713Sgirish hw_p, 463144961713Sgirish p_dip, 463244961713Sgirish hw_p->ndevs)); 463344961713Sgirish break; 463444961713Sgirish } 463544961713Sgirish } 463644961713Sgirish 463744961713Sgirish if (hw_p == NULL) { 463844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 463944961713Sgirish "==> nxge_init_common_device:func # %d " 464044961713Sgirish "parent dip $%p (new)", 464144961713Sgirish nxgep->function_num, 464244961713Sgirish p_dip)); 464344961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 464444961713Sgirish hw_p->parent_devp = p_dip; 464544961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 464644961713Sgirish nxgep->nxge_hw_p = hw_p; 464744961713Sgirish hw_p->ndevs++; 464844961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 464944961713Sgirish hw_p->next = nxge_hw_list; 465044961713Sgirish 465144961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 465244961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 465344961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 465444961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 465544961713Sgirish MUTEX_INIT(&hw_p->nxge_mii_lock, NULL, MUTEX_DRIVER, NULL); 465644961713Sgirish 465744961713Sgirish nxge_hw_list = hw_p; 465844961713Sgirish } 465944961713Sgirish 466044961713Sgirish MUTEX_EXIT(&nxge_common_lock); 466144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 466244961713Sgirish "==> nxge_init_common_device (nxge_hw_list) $%p", 466344961713Sgirish nxge_hw_list)); 466444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 466544961713Sgirish 466644961713Sgirish return (NXGE_OK); 466744961713Sgirish } 466844961713Sgirish 466944961713Sgirish static void 467044961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 467144961713Sgirish { 467244961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 467344961713Sgirish dev_info_t *p_dip; 467444961713Sgirish 467544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 467644961713Sgirish if (nxgep->nxge_hw_p == NULL) { 467744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 467844961713Sgirish "<== nxge_uninit_common_device (no common)")); 467944961713Sgirish return; 468044961713Sgirish } 468144961713Sgirish 468244961713Sgirish MUTEX_ENTER(&nxge_common_lock); 468344961713Sgirish h_hw_p = nxge_hw_list; 468444961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 468544961713Sgirish p_dip = hw_p->parent_devp; 468644961713Sgirish if (nxgep->nxge_hw_p == hw_p && 468744961713Sgirish p_dip == nxgep->p_dip && 468844961713Sgirish nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 468944961713Sgirish hw_p->magic == NXGE_NEPTUNE_MAGIC) { 469044961713Sgirish 469144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 469244961713Sgirish "==> nxge_uninit_common_device:func # %d " 469344961713Sgirish "hw_p $%p parent dip $%p " 469444961713Sgirish "ndevs %d (found)", 469544961713Sgirish nxgep->function_num, 469644961713Sgirish hw_p, 469744961713Sgirish p_dip, 469844961713Sgirish hw_p->ndevs)); 469944961713Sgirish 470044961713Sgirish nxgep->nxge_hw_p = NULL; 470144961713Sgirish if (hw_p->ndevs) { 470244961713Sgirish hw_p->ndevs--; 470344961713Sgirish } 470444961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 470544961713Sgirish if (!hw_p->ndevs) { 470644961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 470744961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 470844961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 470944961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 471044961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mii_lock); 471144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 471244961713Sgirish "==> nxge_uninit_common_device: " 471344961713Sgirish "func # %d " 471444961713Sgirish "hw_p $%p parent dip $%p " 471544961713Sgirish "ndevs %d (last)", 471644961713Sgirish nxgep->function_num, 471744961713Sgirish hw_p, 471844961713Sgirish p_dip, 471944961713Sgirish hw_p->ndevs)); 472044961713Sgirish 472144961713Sgirish if (hw_p == nxge_hw_list) { 472244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 472344961713Sgirish "==> nxge_uninit_common_device:" 472444961713Sgirish "remove head func # %d " 472544961713Sgirish "hw_p $%p parent dip $%p " 472644961713Sgirish "ndevs %d (head)", 472744961713Sgirish nxgep->function_num, 472844961713Sgirish hw_p, 472944961713Sgirish p_dip, 473044961713Sgirish hw_p->ndevs)); 473144961713Sgirish nxge_hw_list = hw_p->next; 473244961713Sgirish } else { 473344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 473444961713Sgirish "==> nxge_uninit_common_device:" 473544961713Sgirish "remove middle func # %d " 473644961713Sgirish "hw_p $%p parent dip $%p " 473744961713Sgirish "ndevs %d (middle)", 473844961713Sgirish nxgep->function_num, 473944961713Sgirish hw_p, 474044961713Sgirish p_dip, 474144961713Sgirish hw_p->ndevs)); 474244961713Sgirish h_hw_p->next = hw_p->next; 474344961713Sgirish } 474444961713Sgirish 474544961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 474644961713Sgirish } 474744961713Sgirish break; 474844961713Sgirish } else { 474944961713Sgirish h_hw_p = hw_p; 475044961713Sgirish } 475144961713Sgirish } 475244961713Sgirish 475344961713Sgirish MUTEX_EXIT(&nxge_common_lock); 475444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 475544961713Sgirish "==> nxge_uninit_common_device (nxge_hw_list) $%p", 475644961713Sgirish nxge_hw_list)); 475744961713Sgirish 475844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 475944961713Sgirish } 4760