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