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