144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2230ac2e7bSml * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish /* 2944961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 3044961713Sgirish */ 3144961713Sgirish #include <sys/nxge/nxge_impl.h> 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 /* 38ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 39ec090658Sml * (This PSARC case is limited to MSI-X vectors 40ec090658Sml * and SPARC platforms only). 4144961713Sgirish */ 42ec090658Sml #if defined(_BIG_ENDIAN) 43ec090658Sml uint32_t nxge_msi_enable = 2; 44ec090658Sml #else 45ec090658Sml uint32_t nxge_msi_enable = 1; 46ec090658Sml #endif 4744961713Sgirish 4844961713Sgirish /* 4944961713Sgirish * Globals: tunable parameters (/etc/system or adb) 5044961713Sgirish * 5144961713Sgirish */ 5244961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 5344961713Sgirish uint32_t nxge_rbr_spare_size = 0; 5444961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 5544961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 56b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 5744961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 5844961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 5944961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 6044961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 6144961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 6244961713Sgirish boolean_t nxge_jumbo_enable = B_FALSE; 6344961713Sgirish uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT; 6444961713Sgirish uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD; 651f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 6644961713Sgirish 6730ac2e7bSml /* MAX LSO size */ 6830ac2e7bSml #define NXGE_LSO_MAXLEN 65535 6930ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 7030ac2e7bSml 7144961713Sgirish /* 7244961713Sgirish * Debugging flags: 7344961713Sgirish * nxge_no_tx_lb : transmit load balancing 7444961713Sgirish * nxge_tx_lb_policy: 0 - TCP port (default) 7544961713Sgirish * 3 - DEST MAC 7644961713Sgirish */ 7744961713Sgirish uint32_t nxge_no_tx_lb = 0; 7844961713Sgirish uint32_t nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP; 7944961713Sgirish 8044961713Sgirish /* 8144961713Sgirish * Add tunable to reduce the amount of time spent in the 8244961713Sgirish * ISR doing Rx Processing. 8344961713Sgirish */ 8444961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 8544961713Sgirish 8644961713Sgirish /* 8744961713Sgirish * Tunables to manage the receive buffer blocks. 8844961713Sgirish * 8944961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 9044961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 9144961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 9244961713Sgirish */ 9344961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 9444961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 9544961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 9644961713Sgirish 9744961713Sgirish rtrace_t npi_rtracebuf; 9844961713Sgirish 9944961713Sgirish #if defined(sun4v) 10044961713Sgirish /* 10144961713Sgirish * Hypervisor N2/NIU services information. 10244961713Sgirish */ 10344961713Sgirish static hsvc_info_t niu_hsvc = { 10444961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 10544961713Sgirish NIU_MINOR_VER, "nxge" 10644961713Sgirish }; 10744961713Sgirish #endif 10844961713Sgirish 10944961713Sgirish /* 11044961713Sgirish * Function Prototypes 11144961713Sgirish */ 11244961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 11344961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 11444961713Sgirish static void nxge_unattach(p_nxge_t); 11544961713Sgirish 11644961713Sgirish #if NXGE_PROPERTY 11744961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 11844961713Sgirish #endif 11944961713Sgirish 12044961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 12144961713Sgirish 12244961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 12344961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 12444961713Sgirish 12544961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 12644961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 12744961713Sgirish #ifdef NXGE_DEBUG 12844961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 12944961713Sgirish #endif 13044961713Sgirish 13144961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 13244961713Sgirish static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep); 13344961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 13444961713Sgirish static void nxge_remove_soft_intrs(p_nxge_t nxgep); 13544961713Sgirish 13644961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 13744961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 13844961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 13944961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 14044961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 14144961713Sgirish 14244961713Sgirish static void nxge_suspend(p_nxge_t); 14344961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 14444961713Sgirish 14544961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 14644961713Sgirish static void nxge_destroy_dev(p_nxge_t); 14744961713Sgirish 14844961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 14944961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 15044961713Sgirish 15144961713Sgirish static nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 15244961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 15344961713Sgirish 15444961713Sgirish static nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 15544961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 15644961713Sgirish 15744961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 15844961713Sgirish struct ddi_dma_attr *, 15944961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 16044961713Sgirish p_nxge_dma_common_t); 16144961713Sgirish 16244961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 16344961713Sgirish 16444961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 16544961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 16644961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 16744961713Sgirish 16844961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 16944961713Sgirish p_nxge_dma_common_t *, size_t); 17044961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 17144961713Sgirish 17244961713Sgirish static nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 17344961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 17444961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 17544961713Sgirish 17644961713Sgirish static nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 17744961713Sgirish p_nxge_dma_common_t *, 17844961713Sgirish size_t); 17944961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 18044961713Sgirish 18144961713Sgirish static int nxge_init_common_dev(p_nxge_t); 18244961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 18344961713Sgirish 18444961713Sgirish /* 18544961713Sgirish * The next declarations are for the GLDv3 interface. 18644961713Sgirish */ 18744961713Sgirish static int nxge_m_start(void *); 18844961713Sgirish static void nxge_m_stop(void *); 18944961713Sgirish static int nxge_m_unicst(void *, const uint8_t *); 19044961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 19144961713Sgirish static int nxge_m_promisc(void *, boolean_t); 19244961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 19344961713Sgirish static void nxge_m_resources(void *); 19444961713Sgirish mblk_t *nxge_m_tx(void *arg, mblk_t *); 19544961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t); 19658324dfcSspeer static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 19758324dfcSspeer mac_addr_slot_t slot); 19858324dfcSspeer static void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 19958324dfcSspeer boolean_t factory); 20058324dfcSspeer static int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 20158324dfcSspeer static int nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr); 20258324dfcSspeer static int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 20358324dfcSspeer static int nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 20458324dfcSspeer static int nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 205*1bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 206*1bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 207*1bd6825cSml uint_t, const void *); 208*1bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 209*1bd6825cSml uint_t, void *); 210*1bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 211*1bd6825cSml const void *); 212*1bd6825cSml static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, 213*1bd6825cSml void *); 214*1bd6825cSml 215*1bd6825cSml #define NXGE_M_CALLBACK_FLAGS\ 216*1bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 217*1bd6825cSml 21844961713Sgirish 21944961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 22044961713Sgirish #define MAX_DUMP_SZ 256 22144961713Sgirish 222*1bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 223*1bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 22444961713Sgirish 22544961713Sgirish static mac_callbacks_t nxge_m_callbacks = { 22644961713Sgirish NXGE_M_CALLBACK_FLAGS, 22744961713Sgirish nxge_m_stat, 22844961713Sgirish nxge_m_start, 22944961713Sgirish nxge_m_stop, 23044961713Sgirish nxge_m_promisc, 23144961713Sgirish nxge_m_multicst, 23244961713Sgirish nxge_m_unicst, 23344961713Sgirish nxge_m_tx, 23444961713Sgirish nxge_m_resources, 23544961713Sgirish nxge_m_ioctl, 236*1bd6825cSml nxge_m_getcapab, 237*1bd6825cSml NULL, 238*1bd6825cSml NULL, 239*1bd6825cSml nxge_m_setprop, 240*1bd6825cSml nxge_m_getprop 24144961713Sgirish }; 24244961713Sgirish 24344961713Sgirish void 24444961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 24544961713Sgirish 246ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 247ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 248ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 249ec090658Sml static int nxge_create_msi_property(p_nxge_t); 250ec090658Sml 25144961713Sgirish /* 25244961713Sgirish * These global variables control the message 25344961713Sgirish * output. 25444961713Sgirish */ 25544961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 25644961713Sgirish uint64_t nxge_debug_level = 0; 25744961713Sgirish 25844961713Sgirish /* 25944961713Sgirish * This list contains the instance structures for the Neptune 26044961713Sgirish * devices present in the system. The lock exists to guarantee 26144961713Sgirish * mutually exclusive access to the list. 26244961713Sgirish */ 26344961713Sgirish void *nxge_list = NULL; 26444961713Sgirish 26544961713Sgirish void *nxge_hw_list = NULL; 26644961713Sgirish nxge_os_mutex_t nxge_common_lock; 26744961713Sgirish 26844961713Sgirish extern uint64_t npi_debug_level; 26944961713Sgirish 27044961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 27144961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 27244961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 27344961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 27444961713Sgirish extern void nxge_fm_init(p_nxge_t, 27544961713Sgirish ddi_device_acc_attr_t *, 27644961713Sgirish ddi_device_acc_attr_t *, 27744961713Sgirish ddi_dma_attr_t *); 27844961713Sgirish extern void nxge_fm_fini(p_nxge_t); 27958324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 28044961713Sgirish 28144961713Sgirish /* 28244961713Sgirish * Count used to maintain the number of buffers being used 28344961713Sgirish * by Neptune instances and loaned up to the upper layers. 28444961713Sgirish */ 28544961713Sgirish uint32_t nxge_mblks_pending = 0; 28644961713Sgirish 28744961713Sgirish /* 28844961713Sgirish * Device register access attributes for PIO. 28944961713Sgirish */ 29044961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 29144961713Sgirish DDI_DEVICE_ATTR_V0, 29244961713Sgirish DDI_STRUCTURE_LE_ACC, 29344961713Sgirish DDI_STRICTORDER_ACC, 29444961713Sgirish }; 29544961713Sgirish 29644961713Sgirish /* 29744961713Sgirish * Device descriptor access attributes for DMA. 29844961713Sgirish */ 29944961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 30044961713Sgirish DDI_DEVICE_ATTR_V0, 30144961713Sgirish DDI_STRUCTURE_LE_ACC, 30244961713Sgirish DDI_STRICTORDER_ACC 30344961713Sgirish }; 30444961713Sgirish 30544961713Sgirish /* 30644961713Sgirish * Device buffer access attributes for DMA. 30744961713Sgirish */ 30844961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 30944961713Sgirish DDI_DEVICE_ATTR_V0, 31044961713Sgirish DDI_STRUCTURE_BE_ACC, 31144961713Sgirish DDI_STRICTORDER_ACC 31244961713Sgirish }; 31344961713Sgirish 31444961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 31544961713Sgirish DMA_ATTR_V0, /* version number. */ 31644961713Sgirish 0, /* low address */ 31744961713Sgirish 0xffffffffffffffff, /* high address */ 31844961713Sgirish 0xffffffffffffffff, /* address counter max */ 31944961713Sgirish #ifndef NIU_PA_WORKAROUND 32044961713Sgirish 0x100000, /* alignment */ 32144961713Sgirish #else 32244961713Sgirish 0x2000, 32344961713Sgirish #endif 32444961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 32544961713Sgirish 0x1, /* minimum transfer size */ 32644961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 32744961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 32844961713Sgirish 1, /* scatter/gather list length */ 32944961713Sgirish (unsigned int) 1, /* granularity */ 33044961713Sgirish 0 /* attribute flags */ 33144961713Sgirish }; 33244961713Sgirish 33344961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 33444961713Sgirish DMA_ATTR_V0, /* version number. */ 33544961713Sgirish 0, /* low address */ 33644961713Sgirish 0xffffffffffffffff, /* high address */ 33744961713Sgirish 0xffffffffffffffff, /* address counter max */ 33844961713Sgirish #if defined(_BIG_ENDIAN) 33944961713Sgirish 0x2000, /* alignment */ 34044961713Sgirish #else 34144961713Sgirish 0x1000, /* alignment */ 34244961713Sgirish #endif 34344961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 34444961713Sgirish 0x1, /* minimum transfer size */ 34544961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 34644961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 34744961713Sgirish 5, /* scatter/gather list length */ 34844961713Sgirish (unsigned int) 1, /* granularity */ 34944961713Sgirish 0 /* attribute flags */ 35044961713Sgirish }; 35144961713Sgirish 35244961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 35344961713Sgirish DMA_ATTR_V0, /* version number. */ 35444961713Sgirish 0, /* low address */ 35544961713Sgirish 0xffffffffffffffff, /* high address */ 35644961713Sgirish 0xffffffffffffffff, /* address counter max */ 35744961713Sgirish 0x2000, /* alignment */ 35844961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 35944961713Sgirish 0x1, /* minimum transfer size */ 36044961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 36144961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 36244961713Sgirish 1, /* scatter/gather list length */ 36344961713Sgirish (unsigned int) 1, /* granularity */ 3640e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 36544961713Sgirish }; 36644961713Sgirish 36744961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 36844961713Sgirish (uint_t)0, /* dlim_addr_lo */ 36944961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 37044961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 37144961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 37244961713Sgirish 0x1, /* dlim_minxfer */ 37344961713Sgirish 1024 /* dlim_speed */ 37444961713Sgirish }; 37544961713Sgirish 37644961713Sgirish dma_method_t nxge_force_dma = DVMA; 37744961713Sgirish 37844961713Sgirish /* 37944961713Sgirish * dma chunk sizes. 38044961713Sgirish * 38144961713Sgirish * Try to allocate the largest possible size 38244961713Sgirish * so that fewer number of dma chunks would be managed 38344961713Sgirish */ 38444961713Sgirish #ifdef NIU_PA_WORKAROUND 38544961713Sgirish size_t alloc_sizes [] = {0x2000}; 38644961713Sgirish #else 38744961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 38844961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 38930ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 39030ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 39144961713Sgirish #endif 39244961713Sgirish 39344961713Sgirish /* 39444961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 39544961713Sgirish */ 39644961713Sgirish 39744961713Sgirish static int 39844961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 39944961713Sgirish { 40044961713Sgirish p_nxge_t nxgep = NULL; 40144961713Sgirish int instance; 40244961713Sgirish int status = DDI_SUCCESS; 40344961713Sgirish uint8_t portn; 40458324dfcSspeer nxge_mmac_t *mmac_info; 40544961713Sgirish 40644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 40744961713Sgirish 40844961713Sgirish /* 40944961713Sgirish * Get the device instance since we'll need to setup 41044961713Sgirish * or retrieve a soft state for this instance. 41144961713Sgirish */ 41244961713Sgirish instance = ddi_get_instance(dip); 41344961713Sgirish 41444961713Sgirish switch (cmd) { 41544961713Sgirish case DDI_ATTACH: 41644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 41744961713Sgirish break; 41844961713Sgirish 41944961713Sgirish case DDI_RESUME: 42044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 42144961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 42244961713Sgirish if (nxgep == NULL) { 42344961713Sgirish status = DDI_FAILURE; 42444961713Sgirish break; 42544961713Sgirish } 42644961713Sgirish if (nxgep->dip != dip) { 42744961713Sgirish status = DDI_FAILURE; 42844961713Sgirish break; 42944961713Sgirish } 43044961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 43144961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 43244961713Sgirish } else { 43356d930aeSspeer status = nxge_resume(nxgep); 43444961713Sgirish } 43544961713Sgirish goto nxge_attach_exit; 43644961713Sgirish 43744961713Sgirish case DDI_PM_RESUME: 43844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 43944961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 44044961713Sgirish if (nxgep == NULL) { 44144961713Sgirish status = DDI_FAILURE; 44244961713Sgirish break; 44344961713Sgirish } 44444961713Sgirish if (nxgep->dip != dip) { 44544961713Sgirish status = DDI_FAILURE; 44644961713Sgirish break; 44744961713Sgirish } 44856d930aeSspeer status = nxge_resume(nxgep); 44944961713Sgirish goto nxge_attach_exit; 45044961713Sgirish 45144961713Sgirish default: 45244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 45344961713Sgirish status = DDI_FAILURE; 45444961713Sgirish goto nxge_attach_exit; 45544961713Sgirish } 45644961713Sgirish 45744961713Sgirish 45844961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 45944961713Sgirish status = DDI_FAILURE; 46044961713Sgirish goto nxge_attach_exit; 46144961713Sgirish } 46244961713Sgirish 46344961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 46444961713Sgirish if (nxgep == NULL) { 4652e59129aSraghus status = NXGE_ERROR; 4662e59129aSraghus goto nxge_attach_fail2; 46744961713Sgirish } 46844961713Sgirish 46998ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 47098ecde52Stm 47144961713Sgirish nxgep->drv_state = 0; 47244961713Sgirish nxgep->dip = dip; 47344961713Sgirish nxgep->instance = instance; 47444961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 47544961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 47644961713Sgirish npi_debug_level = nxge_debug_level; 47744961713Sgirish 47844961713Sgirish nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_dev_desc_dma_acc_attr, 47944961713Sgirish &nxge_rx_dma_attr); 48044961713Sgirish 48144961713Sgirish status = nxge_map_regs(nxgep); 48244961713Sgirish if (status != NXGE_OK) { 48344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 4842e59129aSraghus goto nxge_attach_fail3; 48544961713Sgirish } 48644961713Sgirish 48744961713Sgirish status = nxge_init_common_dev(nxgep); 48844961713Sgirish if (status != NXGE_OK) { 48944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 49044961713Sgirish "nxge_init_common_dev failed")); 4912e59129aSraghus goto nxge_attach_fail4; 49244961713Sgirish } 49344961713Sgirish 49459ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 49559ac0c16Sdavemq if (nxgep->function_num > 1) { 4964202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 49759ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 49859ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 49959ac0c16Sdavemq status = NXGE_ERROR; 5002e59129aSraghus goto nxge_attach_fail4; 50159ac0c16Sdavemq } 50259ac0c16Sdavemq } 50359ac0c16Sdavemq 50444961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 50544961713Sgirish nxgep->mac.portnum = portn; 50644961713Sgirish if ((portn == 0) || (portn == 1)) 50744961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 50844961713Sgirish else 50944961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 51058324dfcSspeer /* 51158324dfcSspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 51258324dfcSspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 51358324dfcSspeer * The two types of MACs have different characterizations. 51458324dfcSspeer */ 51558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 51658324dfcSspeer if (nxgep->function_num < 2) { 51758324dfcSspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 51858324dfcSspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 51958324dfcSspeer } else { 52058324dfcSspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 52158324dfcSspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 52258324dfcSspeer } 52344961713Sgirish /* 52444961713Sgirish * Setup the Ndd parameters for the this instance. 52544961713Sgirish */ 52644961713Sgirish nxge_init_param(nxgep); 52744961713Sgirish 52844961713Sgirish /* 52944961713Sgirish * Setup Register Tracing Buffer. 53044961713Sgirish */ 53144961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 53244961713Sgirish 53344961713Sgirish /* init stats ptr */ 53444961713Sgirish nxge_init_statsp(nxgep); 53556d930aeSspeer 5362e59129aSraghus /* 5372e59129aSraghus * read the vpd info from the eeprom into local data 5382e59129aSraghus * structure and check for the VPD info validity 5392e59129aSraghus */ 5402e59129aSraghus nxge_vpd_info_get(nxgep); 54156d930aeSspeer 5422e59129aSraghus status = nxge_xcvr_find(nxgep); 54344961713Sgirish 54444961713Sgirish if (status != NXGE_OK) { 54556d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 54644961713Sgirish " Couldn't determine card type" 54744961713Sgirish " .... exit ")); 5482e59129aSraghus goto nxge_attach_fail5; 54944961713Sgirish } 55044961713Sgirish 55144961713Sgirish status = nxge_get_config_properties(nxgep); 55244961713Sgirish 55344961713Sgirish if (status != NXGE_OK) { 55444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "get_hw create failed")); 55544961713Sgirish goto nxge_attach_fail; 55644961713Sgirish } 55744961713Sgirish 55844961713Sgirish /* 55944961713Sgirish * Setup the Kstats for the driver. 56044961713Sgirish */ 56144961713Sgirish nxge_setup_kstats(nxgep); 56244961713Sgirish 56344961713Sgirish nxge_setup_param(nxgep); 56444961713Sgirish 56544961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 56644961713Sgirish if (status != NXGE_OK) { 56744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 56844961713Sgirish goto nxge_attach_fail; 56944961713Sgirish } 57044961713Sgirish 57144961713Sgirish #if defined(sun4v) 57244961713Sgirish if (nxgep->niu_type == N2_NIU) { 57344961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 57444961713Sgirish bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 57544961713Sgirish if ((status = 57644961713Sgirish hsvc_register(&nxgep->niu_hsvc, 57744961713Sgirish &nxgep->niu_min_ver)) != 0) { 57844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57944961713Sgirish "nxge_attach: " 58044961713Sgirish "%s: cannot negotiate " 58144961713Sgirish "hypervisor services " 58244961713Sgirish "revision %d " 58344961713Sgirish "group: 0x%lx " 58444961713Sgirish "major: 0x%lx minor: 0x%lx " 58544961713Sgirish "errno: %d", 58644961713Sgirish niu_hsvc.hsvc_modname, 58744961713Sgirish niu_hsvc.hsvc_rev, 58844961713Sgirish niu_hsvc.hsvc_group, 58944961713Sgirish niu_hsvc.hsvc_major, 59044961713Sgirish niu_hsvc.hsvc_minor, 59144961713Sgirish status)); 59244961713Sgirish status = DDI_FAILURE; 59344961713Sgirish goto nxge_attach_fail; 59444961713Sgirish } 59544961713Sgirish 59644961713Sgirish nxgep->niu_hsvc_available = B_TRUE; 59744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 59844961713Sgirish "NIU Hypervisor service enabled")); 59944961713Sgirish } 60044961713Sgirish #endif 60144961713Sgirish 60244961713Sgirish nxge_hw_id_init(nxgep); 60344961713Sgirish nxge_hw_init_niu_common(nxgep); 60444961713Sgirish 60544961713Sgirish status = nxge_setup_mutexes(nxgep); 60644961713Sgirish if (status != NXGE_OK) { 60744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 60844961713Sgirish goto nxge_attach_fail; 60944961713Sgirish } 61044961713Sgirish 61144961713Sgirish status = nxge_setup_dev(nxgep); 61244961713Sgirish if (status != DDI_SUCCESS) { 61344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 61444961713Sgirish goto nxge_attach_fail; 61544961713Sgirish } 61644961713Sgirish 61744961713Sgirish status = nxge_add_intrs(nxgep); 61844961713Sgirish if (status != DDI_SUCCESS) { 61944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 62044961713Sgirish goto nxge_attach_fail; 62144961713Sgirish } 62244961713Sgirish status = nxge_add_soft_intrs(nxgep); 62344961713Sgirish if (status != DDI_SUCCESS) { 62444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "add_soft_intr failed")); 62544961713Sgirish goto nxge_attach_fail; 62644961713Sgirish } 62744961713Sgirish 62844961713Sgirish /* 62944961713Sgirish * Enable interrupts. 63044961713Sgirish */ 63144961713Sgirish nxge_intrs_enable(nxgep); 63244961713Sgirish 6332e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 63444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 63544961713Sgirish "unable to register to mac layer (%d)", status)); 63644961713Sgirish goto nxge_attach_fail; 63744961713Sgirish } 63844961713Sgirish 63944961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 64044961713Sgirish 64144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "registered to mac (instance %d)", 64244961713Sgirish instance)); 64344961713Sgirish 64444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 64544961713Sgirish 64644961713Sgirish goto nxge_attach_exit; 64744961713Sgirish 64844961713Sgirish nxge_attach_fail: 64944961713Sgirish nxge_unattach(nxgep); 6502e59129aSraghus goto nxge_attach_fail1; 6512e59129aSraghus 6522e59129aSraghus nxge_attach_fail5: 6532e59129aSraghus /* 6542e59129aSraghus * Tear down the ndd parameters setup. 6552e59129aSraghus */ 6562e59129aSraghus nxge_destroy_param(nxgep); 6572e59129aSraghus 6582e59129aSraghus /* 6592e59129aSraghus * Tear down the kstat setup. 6602e59129aSraghus */ 6612e59129aSraghus nxge_destroy_kstats(nxgep); 6622e59129aSraghus 6632e59129aSraghus nxge_attach_fail4: 6642e59129aSraghus if (nxgep->nxge_hw_p) { 6652e59129aSraghus nxge_uninit_common_dev(nxgep); 6662e59129aSraghus nxgep->nxge_hw_p = NULL; 6672e59129aSraghus } 6682e59129aSraghus 6692e59129aSraghus nxge_attach_fail3: 6702e59129aSraghus /* 6712e59129aSraghus * Unmap the register setup. 6722e59129aSraghus */ 6732e59129aSraghus nxge_unmap_regs(nxgep); 6742e59129aSraghus 6752e59129aSraghus nxge_fm_fini(nxgep); 6762e59129aSraghus 6772e59129aSraghus nxge_attach_fail2: 6782e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 6792e59129aSraghus 6802e59129aSraghus nxge_attach_fail1: 68156d930aeSspeer if (status != NXGE_OK) 68256d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 68344961713Sgirish nxgep = NULL; 68444961713Sgirish 68544961713Sgirish nxge_attach_exit: 68644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 68744961713Sgirish status)); 68844961713Sgirish 68944961713Sgirish return (status); 69044961713Sgirish } 69144961713Sgirish 69244961713Sgirish static int 69344961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 69444961713Sgirish { 69544961713Sgirish int status = DDI_SUCCESS; 69644961713Sgirish int instance; 69744961713Sgirish p_nxge_t nxgep = NULL; 69844961713Sgirish 69944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 70044961713Sgirish instance = ddi_get_instance(dip); 70144961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 70244961713Sgirish if (nxgep == NULL) { 70344961713Sgirish status = DDI_FAILURE; 70444961713Sgirish goto nxge_detach_exit; 70544961713Sgirish } 70644961713Sgirish 70744961713Sgirish switch (cmd) { 70844961713Sgirish case DDI_DETACH: 70944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 71044961713Sgirish break; 71144961713Sgirish 71244961713Sgirish case DDI_PM_SUSPEND: 71344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 71444961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 71544961713Sgirish nxge_suspend(nxgep); 71644961713Sgirish break; 71744961713Sgirish 71844961713Sgirish case DDI_SUSPEND: 71944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 72044961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 72144961713Sgirish nxgep->suspended = DDI_SUSPEND; 72244961713Sgirish nxge_suspend(nxgep); 72344961713Sgirish } 72444961713Sgirish break; 72544961713Sgirish 72644961713Sgirish default: 72744961713Sgirish status = DDI_FAILURE; 72844961713Sgirish } 72944961713Sgirish 73044961713Sgirish if (cmd != DDI_DETACH) 73144961713Sgirish goto nxge_detach_exit; 73244961713Sgirish 73344961713Sgirish /* 73444961713Sgirish * Stop the xcvr polling. 73544961713Sgirish */ 73644961713Sgirish nxgep->suspended = cmd; 73744961713Sgirish 73844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 73944961713Sgirish 74044961713Sgirish if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 74144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 74244961713Sgirish "<== nxge_detach status = 0x%08X", status)); 74344961713Sgirish return (DDI_FAILURE); 74444961713Sgirish } 74544961713Sgirish 74644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 74744961713Sgirish "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 74844961713Sgirish 74944961713Sgirish nxge_unattach(nxgep); 75044961713Sgirish nxgep = NULL; 75144961713Sgirish 75244961713Sgirish nxge_detach_exit: 75344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 75444961713Sgirish status)); 75544961713Sgirish 75644961713Sgirish return (status); 75744961713Sgirish } 75844961713Sgirish 75944961713Sgirish static void 76044961713Sgirish nxge_unattach(p_nxge_t nxgep) 76144961713Sgirish { 76244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 76344961713Sgirish 76444961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 76544961713Sgirish return; 76644961713Sgirish } 76744961713Sgirish 76898ecde52Stm nxgep->nxge_magic = 0; 76998ecde52Stm 77044961713Sgirish if (nxgep->nxge_timerid) { 77144961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 77244961713Sgirish nxgep->nxge_timerid = 0; 77344961713Sgirish } 77444961713Sgirish 77553560810Ssbehera if (nxgep->nxge_hw_p) { 77653560810Ssbehera nxge_uninit_common_dev(nxgep); 77753560810Ssbehera nxgep->nxge_hw_p = NULL; 77853560810Ssbehera } 77953560810Ssbehera 78044961713Sgirish #if defined(sun4v) 78144961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 78244961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 78344961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 78444961713Sgirish } 78544961713Sgirish #endif 78644961713Sgirish /* 78744961713Sgirish * Stop any further interrupts. 78844961713Sgirish */ 78944961713Sgirish nxge_remove_intrs(nxgep); 79044961713Sgirish 79144961713Sgirish /* remove soft interrups */ 79244961713Sgirish nxge_remove_soft_intrs(nxgep); 79344961713Sgirish 79444961713Sgirish /* 79544961713Sgirish * Stop the device and free resources. 79644961713Sgirish */ 79744961713Sgirish nxge_destroy_dev(nxgep); 79844961713Sgirish 79944961713Sgirish /* 80044961713Sgirish * Tear down the ndd parameters setup. 80144961713Sgirish */ 80244961713Sgirish nxge_destroy_param(nxgep); 80344961713Sgirish 80444961713Sgirish /* 80544961713Sgirish * Tear down the kstat setup. 80644961713Sgirish */ 80744961713Sgirish nxge_destroy_kstats(nxgep); 80844961713Sgirish 80944961713Sgirish /* 81044961713Sgirish * Destroy all mutexes. 81144961713Sgirish */ 81244961713Sgirish nxge_destroy_mutexes(nxgep); 81344961713Sgirish 81444961713Sgirish /* 81544961713Sgirish * Remove the list of ndd parameters which 81644961713Sgirish * were setup during attach. 81744961713Sgirish */ 81844961713Sgirish if (nxgep->dip) { 81944961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 82044961713Sgirish " nxge_unattach: remove all properties")); 82144961713Sgirish 82244961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 82344961713Sgirish } 82444961713Sgirish 82544961713Sgirish #if NXGE_PROPERTY 82644961713Sgirish nxge_remove_hard_properties(nxgep); 82744961713Sgirish #endif 82844961713Sgirish 82944961713Sgirish /* 83044961713Sgirish * Unmap the register setup. 83144961713Sgirish */ 83244961713Sgirish nxge_unmap_regs(nxgep); 83344961713Sgirish 83444961713Sgirish nxge_fm_fini(nxgep); 83544961713Sgirish 83644961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 83744961713Sgirish 83844961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 83944961713Sgirish } 84044961713Sgirish 84144961713Sgirish static char n2_siu_name[] = "niu"; 84244961713Sgirish 84344961713Sgirish static nxge_status_t 84444961713Sgirish nxge_map_regs(p_nxge_t nxgep) 84544961713Sgirish { 84644961713Sgirish int ddi_status = DDI_SUCCESS; 84744961713Sgirish p_dev_regs_t dev_regs; 84844961713Sgirish char buf[MAXPATHLEN + 1]; 84944961713Sgirish char *devname; 85044961713Sgirish #ifdef NXGE_DEBUG 85144961713Sgirish char *sysname; 85244961713Sgirish #endif 85344961713Sgirish off_t regsize; 85444961713Sgirish nxge_status_t status = NXGE_OK; 85514ea4bb7Ssd #if !defined(_BIG_ENDIAN) 85614ea4bb7Ssd off_t pci_offset; 85714ea4bb7Ssd uint16_t pcie_devctl; 85814ea4bb7Ssd #endif 85944961713Sgirish 86044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 86144961713Sgirish nxgep->dev_regs = NULL; 86244961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 86344961713Sgirish dev_regs->nxge_regh = NULL; 86444961713Sgirish dev_regs->nxge_pciregh = NULL; 86544961713Sgirish dev_regs->nxge_msix_regh = NULL; 86644961713Sgirish dev_regs->nxge_vir_regh = NULL; 86744961713Sgirish dev_regs->nxge_vir2_regh = NULL; 86859ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 86944961713Sgirish 87044961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 87144961713Sgirish ASSERT(strlen(devname) > 0); 87244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 87344961713Sgirish "nxge_map_regs: pathname devname %s", devname)); 87444961713Sgirish 87544961713Sgirish if (strstr(devname, n2_siu_name)) { 87644961713Sgirish /* N2/NIU */ 87744961713Sgirish nxgep->niu_type = N2_NIU; 87844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 87944961713Sgirish "nxge_map_regs: N2/NIU devname %s", devname)); 88044961713Sgirish /* get function number */ 88144961713Sgirish nxgep->function_num = 88244961713Sgirish (devname[strlen(devname) -1] == '1' ? 1 : 0); 88344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 88444961713Sgirish "nxge_map_regs: N2/NIU function number %d", 88544961713Sgirish nxgep->function_num)); 88644961713Sgirish } else { 88744961713Sgirish int *prop_val; 88844961713Sgirish uint_t prop_len; 88944961713Sgirish uint8_t func_num; 89044961713Sgirish 89144961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 89244961713Sgirish 0, "reg", 89344961713Sgirish &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 89444961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 89544961713Sgirish "Reg property not found")); 89644961713Sgirish ddi_status = DDI_FAILURE; 89744961713Sgirish goto nxge_map_regs_fail0; 89844961713Sgirish 89944961713Sgirish } else { 90044961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 90144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 90244961713Sgirish "Reg property found: fun # %d", 90344961713Sgirish func_num)); 90444961713Sgirish nxgep->function_num = func_num; 90544961713Sgirish ddi_prop_free(prop_val); 90644961713Sgirish } 90744961713Sgirish } 90844961713Sgirish 90944961713Sgirish switch (nxgep->niu_type) { 91044961713Sgirish default: 91144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 91244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 91344961713Sgirish "nxge_map_regs: pci config size 0x%x", regsize)); 91444961713Sgirish 91544961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 91644961713Sgirish (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 91744961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 91844961713Sgirish if (ddi_status != DDI_SUCCESS) { 91944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 92044961713Sgirish "ddi_map_regs, nxge bus config regs failed")); 92144961713Sgirish goto nxge_map_regs_fail0; 92244961713Sgirish } 92344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 92444961713Sgirish "nxge_map_reg: PCI config addr 0x%0llx " 92544961713Sgirish " handle 0x%0llx", dev_regs->nxge_pciregp, 92644961713Sgirish dev_regs->nxge_pciregh)); 92744961713Sgirish /* 92844961713Sgirish * IMP IMP 92944961713Sgirish * workaround for bit swapping bug in HW 93044961713Sgirish * which ends up in no-snoop = yes 93144961713Sgirish * resulting, in DMA not synched properly 93244961713Sgirish */ 93344961713Sgirish #if !defined(_BIG_ENDIAN) 93414ea4bb7Ssd /* workarounds for x86 systems */ 93514ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 93614ea4bb7Ssd pcie_devctl = 0x0; 93714ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 93814ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 93914ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 94014ea4bb7Ssd pcie_devctl); 94144961713Sgirish #endif 94214ea4bb7Ssd 94344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 94444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 94544961713Sgirish "nxge_map_regs: pio size 0x%x", regsize)); 94644961713Sgirish /* set up the device mapped register */ 94744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 94844961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 94944961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 95044961713Sgirish if (ddi_status != DDI_SUCCESS) { 95144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 95244961713Sgirish "ddi_map_regs for Neptune global reg failed")); 95344961713Sgirish goto nxge_map_regs_fail1; 95444961713Sgirish } 95544961713Sgirish 95644961713Sgirish /* set up the msi/msi-x mapped register */ 95744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 95844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 95944961713Sgirish "nxge_map_regs: msix size 0x%x", regsize)); 96044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 96144961713Sgirish (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 96244961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 96344961713Sgirish if (ddi_status != DDI_SUCCESS) { 96444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 96544961713Sgirish "ddi_map_regs for msi reg failed")); 96644961713Sgirish goto nxge_map_regs_fail2; 96744961713Sgirish } 96844961713Sgirish 96944961713Sgirish /* set up the vio region mapped register */ 97044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 97144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 97244961713Sgirish "nxge_map_regs: vio size 0x%x", regsize)); 97344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 97444961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 97544961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 97644961713Sgirish 97744961713Sgirish if (ddi_status != DDI_SUCCESS) { 97844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 97944961713Sgirish "ddi_map_regs for nxge vio reg failed")); 98044961713Sgirish goto nxge_map_regs_fail3; 98144961713Sgirish } 98244961713Sgirish nxgep->dev_regs = dev_regs; 98344961713Sgirish 98444961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 98544961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 98644961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_pciregp); 98744961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 98844961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 98944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 99044961713Sgirish 99144961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 99244961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 99344961713Sgirish 99444961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 99544961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 99644961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 99744961713Sgirish 99844961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 99944961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 100044961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 100144961713Sgirish 100244961713Sgirish break; 100344961713Sgirish 100444961713Sgirish case N2_NIU: 100544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 100644961713Sgirish /* 100744961713Sgirish * Set up the device mapped register (FWARC 2006/556) 100844961713Sgirish * (changed back to 1: reg starts at 1!) 100944961713Sgirish */ 101044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 101144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 101244961713Sgirish "nxge_map_regs: dev size 0x%x", regsize)); 101344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 101444961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 101544961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 101644961713Sgirish 101744961713Sgirish if (ddi_status != DDI_SUCCESS) { 101844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 101944961713Sgirish "ddi_map_regs for N2/NIU, global reg failed ")); 102044961713Sgirish goto nxge_map_regs_fail1; 102144961713Sgirish } 102244961713Sgirish 102344961713Sgirish /* set up the vio region mapped register */ 102444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 102544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 102644961713Sgirish "nxge_map_regs: vio (1) size 0x%x", regsize)); 102744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 102844961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 102944961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 103044961713Sgirish 103144961713Sgirish if (ddi_status != DDI_SUCCESS) { 103244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 103344961713Sgirish "ddi_map_regs for nxge vio reg failed")); 103444961713Sgirish goto nxge_map_regs_fail2; 103544961713Sgirish } 103644961713Sgirish /* set up the vio region mapped register */ 103744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 103844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 103944961713Sgirish "nxge_map_regs: vio (3) size 0x%x", regsize)); 104044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 104144961713Sgirish (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 104244961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 104344961713Sgirish 104444961713Sgirish if (ddi_status != DDI_SUCCESS) { 104544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 104644961713Sgirish "ddi_map_regs for nxge vio2 reg failed")); 104744961713Sgirish goto nxge_map_regs_fail3; 104844961713Sgirish } 104944961713Sgirish nxgep->dev_regs = dev_regs; 105044961713Sgirish 105144961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 105244961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 105344961713Sgirish 105444961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 105544961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 105644961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 105744961713Sgirish 105844961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 105944961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 106044961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 106144961713Sgirish 106244961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 106344961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 106444961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 106544961713Sgirish 106644961713Sgirish break; 106744961713Sgirish } 106844961713Sgirish 106944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 107044961713Sgirish " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 107144961713Sgirish 107244961713Sgirish goto nxge_map_regs_exit; 107344961713Sgirish nxge_map_regs_fail3: 107444961713Sgirish if (dev_regs->nxge_msix_regh) { 107544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 107644961713Sgirish } 107744961713Sgirish if (dev_regs->nxge_vir_regh) { 107844961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 107944961713Sgirish } 108044961713Sgirish nxge_map_regs_fail2: 108144961713Sgirish if (dev_regs->nxge_regh) { 108244961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 108344961713Sgirish } 108444961713Sgirish nxge_map_regs_fail1: 108544961713Sgirish if (dev_regs->nxge_pciregh) { 108644961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 108744961713Sgirish } 108844961713Sgirish nxge_map_regs_fail0: 108944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 109044961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 109144961713Sgirish 109244961713Sgirish nxge_map_regs_exit: 109344961713Sgirish if (ddi_status != DDI_SUCCESS) 109444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 109544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 109644961713Sgirish return (status); 109744961713Sgirish } 109844961713Sgirish 109944961713Sgirish static void 110044961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 110144961713Sgirish { 110244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 110344961713Sgirish if (nxgep->dev_regs) { 110444961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 110544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 110644961713Sgirish "==> nxge_unmap_regs: bus")); 110744961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 110844961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 110944961713Sgirish } 111044961713Sgirish if (nxgep->dev_regs->nxge_regh) { 111144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 111244961713Sgirish "==> nxge_unmap_regs: device registers")); 111344961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 111444961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 111544961713Sgirish } 111644961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 111744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 111844961713Sgirish "==> nxge_unmap_regs: device interrupts")); 111944961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 112044961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 112144961713Sgirish } 112244961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 112344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 112444961713Sgirish "==> nxge_unmap_regs: vio region")); 112544961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 112644961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 112744961713Sgirish } 112844961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 112944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 113044961713Sgirish "==> nxge_unmap_regs: vio2 region")); 113144961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 113244961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 113344961713Sgirish } 113444961713Sgirish 113544961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 113644961713Sgirish nxgep->dev_regs = NULL; 113744961713Sgirish } 113844961713Sgirish 113944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 114044961713Sgirish } 114144961713Sgirish 114244961713Sgirish static nxge_status_t 114344961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 114444961713Sgirish { 114544961713Sgirish int ddi_status = DDI_SUCCESS; 114644961713Sgirish nxge_status_t status = NXGE_OK; 114744961713Sgirish nxge_classify_t *classify_ptr; 114844961713Sgirish int partition; 114944961713Sgirish 115044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 115144961713Sgirish 115244961713Sgirish /* 115344961713Sgirish * Get the interrupt cookie so the mutexes can be 115458324dfcSspeer * Initialized. 115544961713Sgirish */ 115644961713Sgirish ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 115744961713Sgirish &nxgep->interrupt_cookie); 115844961713Sgirish if (ddi_status != DDI_SUCCESS) { 115944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 116044961713Sgirish "<== nxge_setup_mutexes: failed 0x%x", ddi_status)); 116144961713Sgirish goto nxge_setup_mutexes_exit; 116244961713Sgirish } 116344961713Sgirish 116498ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 116598ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 116698ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 116798ecde52Stm 116844961713Sgirish /* 116998ecde52Stm * Initialize mutexes for this device. 117044961713Sgirish */ 117144961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 117244961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 117344961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 117444961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 117544961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 117644961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 117744961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 117844961713Sgirish RW_DRIVER, (void *)nxgep->interrupt_cookie); 117944961713Sgirish 118044961713Sgirish classify_ptr = &nxgep->classifier; 118144961713Sgirish /* 118244961713Sgirish * FFLP Mutexes are never used in interrupt context 118344961713Sgirish * as fflp operation can take very long time to 118444961713Sgirish * complete and hence not suitable to invoke from interrupt 118544961713Sgirish * handlers. 118644961713Sgirish */ 118744961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 118859ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 11892e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 119044961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 119159ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 119244961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 119344961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 119444961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 119544961713Sgirish } 119644961713Sgirish } 119744961713Sgirish 119844961713Sgirish nxge_setup_mutexes_exit: 119944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 120059ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 120144961713Sgirish 120244961713Sgirish if (ddi_status != DDI_SUCCESS) 120344961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 120444961713Sgirish 120544961713Sgirish return (status); 120644961713Sgirish } 120744961713Sgirish 120844961713Sgirish static void 120944961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 121044961713Sgirish { 121144961713Sgirish int partition; 121244961713Sgirish nxge_classify_t *classify_ptr; 121344961713Sgirish 121444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 121544961713Sgirish RW_DESTROY(&nxgep->filter_lock); 121644961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 121744961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 121844961713Sgirish MUTEX_DESTROY(nxgep->genlock); 121944961713Sgirish 122044961713Sgirish classify_ptr = &nxgep->classifier; 122144961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 122244961713Sgirish 122398ecde52Stm /* Destroy all polling resources. */ 122498ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 122598ecde52Stm cv_destroy(&nxgep->poll_cv); 122698ecde52Stm 122798ecde52Stm /* free data structures, based on HW type */ 12282e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 122944961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 123044961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 123144961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 123244961713Sgirish } 123344961713Sgirish } 123444961713Sgirish 123544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 123644961713Sgirish } 123744961713Sgirish 123844961713Sgirish nxge_status_t 123944961713Sgirish nxge_init(p_nxge_t nxgep) 124044961713Sgirish { 124144961713Sgirish nxge_status_t status = NXGE_OK; 124244961713Sgirish 124344961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 124444961713Sgirish 124514ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 124614ea4bb7Ssd return (status); 124714ea4bb7Ssd } 124814ea4bb7Ssd 124944961713Sgirish /* 125044961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 125144961713Sgirish * and receive/transmit descriptor rings. 125244961713Sgirish */ 125344961713Sgirish status = nxge_alloc_mem_pool(nxgep); 125444961713Sgirish if (status != NXGE_OK) { 125544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 125644961713Sgirish goto nxge_init_fail1; 125744961713Sgirish } 125844961713Sgirish 125944961713Sgirish /* 126044961713Sgirish * Initialize and enable TXC registers 126144961713Sgirish * (Globally enable TX controller, 126244961713Sgirish * enable a port, configure dma channel bitmap, 126344961713Sgirish * configure the max burst size). 126444961713Sgirish */ 126544961713Sgirish status = nxge_txc_init(nxgep); 126644961713Sgirish if (status != NXGE_OK) { 126744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txc failed\n")); 126844961713Sgirish goto nxge_init_fail2; 126944961713Sgirish } 127044961713Sgirish 127144961713Sgirish /* 127244961713Sgirish * Initialize and enable TXDMA channels. 127344961713Sgirish */ 127444961713Sgirish status = nxge_init_txdma_channels(nxgep); 127544961713Sgirish if (status != NXGE_OK) { 127644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 127744961713Sgirish goto nxge_init_fail3; 127844961713Sgirish } 127944961713Sgirish 128044961713Sgirish /* 128144961713Sgirish * Initialize and enable RXDMA channels. 128244961713Sgirish */ 128344961713Sgirish status = nxge_init_rxdma_channels(nxgep); 128444961713Sgirish if (status != NXGE_OK) { 128544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 128644961713Sgirish goto nxge_init_fail4; 128744961713Sgirish } 128844961713Sgirish 128944961713Sgirish /* 129044961713Sgirish * Initialize TCAM and FCRAM (Neptune). 129144961713Sgirish */ 129244961713Sgirish status = nxge_classify_init(nxgep); 129344961713Sgirish if (status != NXGE_OK) { 129444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 129544961713Sgirish goto nxge_init_fail5; 129644961713Sgirish } 129744961713Sgirish 129844961713Sgirish /* 129944961713Sgirish * Initialize ZCP 130044961713Sgirish */ 130144961713Sgirish status = nxge_zcp_init(nxgep); 130244961713Sgirish if (status != NXGE_OK) { 130344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 130444961713Sgirish goto nxge_init_fail5; 130544961713Sgirish } 130644961713Sgirish 130744961713Sgirish /* 130844961713Sgirish * Initialize IPP. 130944961713Sgirish */ 131044961713Sgirish status = nxge_ipp_init(nxgep); 131144961713Sgirish if (status != NXGE_OK) { 131244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 131344961713Sgirish goto nxge_init_fail5; 131444961713Sgirish } 131544961713Sgirish 131644961713Sgirish /* 131744961713Sgirish * Initialize the MAC block. 131844961713Sgirish */ 131944961713Sgirish status = nxge_mac_init(nxgep); 132044961713Sgirish if (status != NXGE_OK) { 132144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 132244961713Sgirish goto nxge_init_fail5; 132344961713Sgirish } 132444961713Sgirish 132544961713Sgirish nxge_intrs_enable(nxgep); 132644961713Sgirish 132744961713Sgirish /* 132844961713Sgirish * Enable hardware interrupts. 132944961713Sgirish */ 133044961713Sgirish nxge_intr_hw_enable(nxgep); 133144961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 133244961713Sgirish 133344961713Sgirish goto nxge_init_exit; 133444961713Sgirish 133544961713Sgirish nxge_init_fail5: 133644961713Sgirish nxge_uninit_rxdma_channels(nxgep); 133744961713Sgirish nxge_init_fail4: 133844961713Sgirish nxge_uninit_txdma_channels(nxgep); 133944961713Sgirish nxge_init_fail3: 134044961713Sgirish (void) nxge_txc_uninit(nxgep); 134144961713Sgirish nxge_init_fail2: 134244961713Sgirish nxge_free_mem_pool(nxgep); 134344961713Sgirish nxge_init_fail1: 134444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 134544961713Sgirish "<== nxge_init status (failed) = 0x%08x", status)); 134644961713Sgirish return (status); 134744961713Sgirish 134844961713Sgirish nxge_init_exit: 134944961713Sgirish 135044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 135144961713Sgirish status)); 135244961713Sgirish return (status); 135344961713Sgirish } 135444961713Sgirish 135544961713Sgirish 135644961713Sgirish timeout_id_t 135744961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 135844961713Sgirish { 135944961713Sgirish if ((nxgep->suspended == 0) || 136044961713Sgirish (nxgep->suspended == DDI_RESUME)) { 136144961713Sgirish return (timeout(func, (caddr_t)nxgep, 136244961713Sgirish drv_usectohz(1000 * msec))); 136344961713Sgirish } 136444961713Sgirish return (NULL); 136544961713Sgirish } 136644961713Sgirish 136744961713Sgirish /*ARGSUSED*/ 136844961713Sgirish void 136944961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 137044961713Sgirish { 137144961713Sgirish if (timerid) { 137244961713Sgirish (void) untimeout(timerid); 137344961713Sgirish } 137444961713Sgirish } 137544961713Sgirish 137644961713Sgirish void 137744961713Sgirish nxge_uninit(p_nxge_t nxgep) 137844961713Sgirish { 137944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 138044961713Sgirish 138144961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 138244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 138344961713Sgirish "==> nxge_uninit: not initialized")); 138444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 138544961713Sgirish "<== nxge_uninit")); 138644961713Sgirish return; 138744961713Sgirish } 138844961713Sgirish 138944961713Sgirish /* stop timer */ 139044961713Sgirish if (nxgep->nxge_timerid) { 139144961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 139244961713Sgirish nxgep->nxge_timerid = 0; 139344961713Sgirish } 139444961713Sgirish 139544961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 139644961713Sgirish (void) nxge_intr_hw_disable(nxgep); 139744961713Sgirish 139844961713Sgirish /* 139944961713Sgirish * Reset the receive MAC side. 140044961713Sgirish */ 140144961713Sgirish (void) nxge_rx_mac_disable(nxgep); 140244961713Sgirish 140344961713Sgirish /* Disable and soft reset the IPP */ 140444961713Sgirish (void) nxge_ipp_disable(nxgep); 140544961713Sgirish 1406a3c5bd6dSspeer /* Free classification resources */ 1407a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1408a3c5bd6dSspeer 140944961713Sgirish /* 141044961713Sgirish * Reset the transmit/receive DMA side. 141144961713Sgirish */ 141244961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 141344961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 141444961713Sgirish 141544961713Sgirish nxge_uninit_txdma_channels(nxgep); 141644961713Sgirish nxge_uninit_rxdma_channels(nxgep); 141744961713Sgirish 141844961713Sgirish /* 141944961713Sgirish * Reset the transmit MAC side. 142044961713Sgirish */ 142144961713Sgirish (void) nxge_tx_mac_disable(nxgep); 142244961713Sgirish 142344961713Sgirish nxge_free_mem_pool(nxgep); 142444961713Sgirish 142544961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 142644961713Sgirish 142744961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 142844961713Sgirish 142944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 143044961713Sgirish "nxge_mblks_pending %d", nxge_mblks_pending)); 143144961713Sgirish } 143244961713Sgirish 143344961713Sgirish void 143444961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 143544961713Sgirish { 1436adfcba55Sjoycey #if defined(__i386) 1437adfcba55Sjoycey size_t reg; 1438adfcba55Sjoycey #else 143944961713Sgirish uint64_t reg; 1440adfcba55Sjoycey #endif 144144961713Sgirish uint64_t regdata; 144244961713Sgirish int i, retry; 144344961713Sgirish 144444961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 144544961713Sgirish regdata = 0; 144644961713Sgirish retry = 1; 144744961713Sgirish 144844961713Sgirish for (i = 0; i < retry; i++) { 144944961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 145044961713Sgirish } 145144961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 145244961713Sgirish } 145344961713Sgirish 145444961713Sgirish void 145544961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 145644961713Sgirish { 1457adfcba55Sjoycey #if defined(__i386) 1458adfcba55Sjoycey size_t reg; 1459adfcba55Sjoycey #else 146044961713Sgirish uint64_t reg; 1461adfcba55Sjoycey #endif 146244961713Sgirish uint64_t buf[2]; 146344961713Sgirish 146444961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 14657a8b1321Sjoycey #if defined(__i386) 14667a8b1321Sjoycey reg = (size_t)buf[0]; 14677a8b1321Sjoycey #else 146844961713Sgirish reg = buf[0]; 14697a8b1321Sjoycey #endif 147044961713Sgirish 147144961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 147244961713Sgirish } 147344961713Sgirish 147444961713Sgirish 147544961713Sgirish nxge_os_mutex_t nxgedebuglock; 147644961713Sgirish int nxge_debug_init = 0; 147744961713Sgirish 147844961713Sgirish /*ARGSUSED*/ 147944961713Sgirish /*VARARGS*/ 148044961713Sgirish void 148144961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 148244961713Sgirish { 148344961713Sgirish char msg_buffer[1048]; 148444961713Sgirish char prefix_buffer[32]; 148544961713Sgirish int instance; 148644961713Sgirish uint64_t debug_level; 148744961713Sgirish int cmn_level = CE_CONT; 148844961713Sgirish va_list ap; 148944961713Sgirish 149044961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 149144961713Sgirish nxgep->nxge_debug_level; 149244961713Sgirish 149344961713Sgirish if ((level & debug_level) || 149444961713Sgirish (level == NXGE_NOTE) || 149544961713Sgirish (level == NXGE_ERR_CTL)) { 149644961713Sgirish /* do the msg processing */ 149744961713Sgirish if (nxge_debug_init == 0) { 149844961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 149944961713Sgirish nxge_debug_init = 1; 150044961713Sgirish } 150144961713Sgirish 150244961713Sgirish MUTEX_ENTER(&nxgedebuglock); 150344961713Sgirish 150444961713Sgirish if ((level & NXGE_NOTE)) { 150544961713Sgirish cmn_level = CE_NOTE; 150644961713Sgirish } 150744961713Sgirish 150844961713Sgirish if (level & NXGE_ERR_CTL) { 150944961713Sgirish cmn_level = CE_WARN; 151044961713Sgirish } 151144961713Sgirish 151244961713Sgirish va_start(ap, fmt); 151344961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 151444961713Sgirish va_end(ap); 151544961713Sgirish if (nxgep == NULL) { 151644961713Sgirish instance = -1; 151744961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 151844961713Sgirish } else { 151944961713Sgirish instance = nxgep->instance; 152044961713Sgirish (void) sprintf(prefix_buffer, 152144961713Sgirish "%s%d :", "nxge", instance); 152244961713Sgirish } 152344961713Sgirish 152444961713Sgirish MUTEX_EXIT(&nxgedebuglock); 152544961713Sgirish cmn_err(cmn_level, "!%s %s\n", 152644961713Sgirish prefix_buffer, msg_buffer); 152744961713Sgirish 152844961713Sgirish } 152944961713Sgirish } 153044961713Sgirish 153144961713Sgirish char * 153244961713Sgirish nxge_dump_packet(char *addr, int size) 153344961713Sgirish { 153444961713Sgirish uchar_t *ap = (uchar_t *)addr; 153544961713Sgirish int i; 153644961713Sgirish static char etherbuf[1024]; 153744961713Sgirish char *cp = etherbuf; 153844961713Sgirish char digits[] = "0123456789abcdef"; 153944961713Sgirish 154044961713Sgirish if (!size) 154144961713Sgirish size = 60; 154244961713Sgirish 154344961713Sgirish if (size > MAX_DUMP_SZ) { 154444961713Sgirish /* Dump the leading bytes */ 154544961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 154644961713Sgirish if (*ap > 0x0f) 154744961713Sgirish *cp++ = digits[*ap >> 4]; 154844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 154944961713Sgirish *cp++ = ':'; 155044961713Sgirish } 155144961713Sgirish for (i = 0; i < 20; i++) 155244961713Sgirish *cp++ = '.'; 155344961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 155444961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 155544961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 155644961713Sgirish if (*ap > 0x0f) 155744961713Sgirish *cp++ = digits[*ap >> 4]; 155844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 155944961713Sgirish *cp++ = ':'; 156044961713Sgirish } 156144961713Sgirish } else { 156244961713Sgirish for (i = 0; i < size; i++) { 156344961713Sgirish if (*ap > 0x0f) 156444961713Sgirish *cp++ = digits[*ap >> 4]; 156544961713Sgirish *cp++ = digits[*ap++ & 0xf]; 156644961713Sgirish *cp++ = ':'; 156744961713Sgirish } 156844961713Sgirish } 156944961713Sgirish *--cp = 0; 157044961713Sgirish return (etherbuf); 157144961713Sgirish } 157244961713Sgirish 157344961713Sgirish #ifdef NXGE_DEBUG 157444961713Sgirish static void 157544961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 157644961713Sgirish { 157744961713Sgirish ddi_acc_handle_t cfg_handle; 157844961713Sgirish p_pci_cfg_t cfg_ptr; 157944961713Sgirish ddi_acc_handle_t dev_handle; 158044961713Sgirish char *dev_ptr; 158144961713Sgirish ddi_acc_handle_t pci_config_handle; 158244961713Sgirish uint32_t regval; 158344961713Sgirish int i; 158444961713Sgirish 158544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 158644961713Sgirish 158744961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 158844961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 158944961713Sgirish 15902e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 159144961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 159244961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 159344961713Sgirish 159444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 159559ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 159644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 159759ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 159859ac0c16Sdavemq &cfg_ptr->vendorid)); 159944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 160059ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 160159ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 160259ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 160344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 160459ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 160559ac0c16Sdavemq "bar1c 0x%x", 160659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 160759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 160859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 160959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 161044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 161159ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 161259ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 161359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 161459ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 161559ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 161659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 161744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 161859ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 161959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 162044961713Sgirish 162144961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 162244961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 162344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 162459ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 162559ac0c16Sdavemq "last 0x%llx ", 162659ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 162759ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 162859ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 162959ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 163059ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 163159ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 163259ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 163359ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 163444961713Sgirish } 163544961713Sgirish } 163644961713Sgirish 163744961713Sgirish #endif 163844961713Sgirish 163944961713Sgirish static void 164044961713Sgirish nxge_suspend(p_nxge_t nxgep) 164144961713Sgirish { 164244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 164344961713Sgirish 164444961713Sgirish nxge_intrs_disable(nxgep); 164544961713Sgirish nxge_destroy_dev(nxgep); 164644961713Sgirish 164744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 164844961713Sgirish } 164944961713Sgirish 165044961713Sgirish static nxge_status_t 165144961713Sgirish nxge_resume(p_nxge_t nxgep) 165244961713Sgirish { 165344961713Sgirish nxge_status_t status = NXGE_OK; 165444961713Sgirish 165544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 165644961713Sgirish 165791c98b31Sjoycey nxgep->suspended = DDI_RESUME; 165891c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 165991c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 166091c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 166191c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 166291c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 166391c98b31Sjoycey nxge_intrs_enable(nxgep); 166444961713Sgirish nxgep->suspended = 0; 166544961713Sgirish 166644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 166744961713Sgirish "<== nxge_resume status = 0x%x", status)); 166844961713Sgirish return (status); 166944961713Sgirish } 167044961713Sgirish 167144961713Sgirish static nxge_status_t 167244961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 167344961713Sgirish { 167444961713Sgirish nxge_status_t status = NXGE_OK; 167544961713Sgirish 167644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 167759ac0c16Sdavemq nxgep->mac.portnum)); 167844961713Sgirish 167944961713Sgirish status = nxge_link_init(nxgep); 168014ea4bb7Ssd 168114ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 168214ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 168314ea4bb7Ssd "port%d Bad register acc handle", nxgep->mac.portnum)); 168414ea4bb7Ssd status = NXGE_ERROR; 168514ea4bb7Ssd } 168614ea4bb7Ssd 168744961713Sgirish if (status != NXGE_OK) { 168844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 168944961713Sgirish " nxge_setup_dev status " 169044961713Sgirish "(xcvr init 0x%08x)", status)); 169144961713Sgirish goto nxge_setup_dev_exit; 169244961713Sgirish } 169344961713Sgirish 169444961713Sgirish nxge_setup_dev_exit: 169544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 169644961713Sgirish "<== nxge_setup_dev port %d status = 0x%08x", 169744961713Sgirish nxgep->mac.portnum, status)); 169844961713Sgirish 169944961713Sgirish return (status); 170044961713Sgirish } 170144961713Sgirish 170244961713Sgirish static void 170344961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 170444961713Sgirish { 170544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 170644961713Sgirish 170744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 170844961713Sgirish 170944961713Sgirish (void) nxge_hw_stop(nxgep); 171044961713Sgirish 171144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 171244961713Sgirish } 171344961713Sgirish 171444961713Sgirish static nxge_status_t 171544961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 171644961713Sgirish { 171744961713Sgirish int ddi_status = DDI_SUCCESS; 171844961713Sgirish uint_t count; 171944961713Sgirish ddi_dma_cookie_t cookie; 172044961713Sgirish uint_t iommu_pagesize; 172144961713Sgirish nxge_status_t status = NXGE_OK; 172244961713Sgirish 172344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 172444961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 172544961713Sgirish if (nxgep->niu_type != N2_NIU) { 172644961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 172744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 172844961713Sgirish " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 172944961713Sgirish " default_block_size %d iommu_pagesize %d", 173044961713Sgirish nxgep->sys_page_sz, 173144961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 173244961713Sgirish nxgep->rx_default_block_size, 173344961713Sgirish iommu_pagesize)); 173444961713Sgirish 173544961713Sgirish if (iommu_pagesize != 0) { 173644961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 173744961713Sgirish if (iommu_pagesize > 0x4000) 173844961713Sgirish nxgep->sys_page_sz = 0x4000; 173944961713Sgirish } else { 174044961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 174144961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 174244961713Sgirish } 174344961713Sgirish } 174444961713Sgirish } 174544961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 174644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 174744961713Sgirish "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 174844961713Sgirish "default_block_size %d page mask %d", 174944961713Sgirish nxgep->sys_page_sz, 175044961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 175144961713Sgirish nxgep->rx_default_block_size, 175244961713Sgirish nxgep->sys_page_mask)); 175344961713Sgirish 175444961713Sgirish 175544961713Sgirish switch (nxgep->sys_page_sz) { 175644961713Sgirish default: 175744961713Sgirish nxgep->sys_page_sz = 0x1000; 175844961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 175944961713Sgirish nxgep->rx_default_block_size = 0x1000; 176044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 176144961713Sgirish break; 176244961713Sgirish case 0x1000: 176344961713Sgirish nxgep->rx_default_block_size = 0x1000; 176444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 176544961713Sgirish break; 176644961713Sgirish case 0x2000: 176744961713Sgirish nxgep->rx_default_block_size = 0x2000; 176844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 176944961713Sgirish break; 177044961713Sgirish case 0x4000: 177144961713Sgirish nxgep->rx_default_block_size = 0x4000; 177244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 177344961713Sgirish break; 177444961713Sgirish case 0x8000: 177544961713Sgirish nxgep->rx_default_block_size = 0x8000; 177644961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 177744961713Sgirish break; 177844961713Sgirish } 177944961713Sgirish 178044961713Sgirish #ifndef USE_RX_BIG_BUF 178144961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 178244961713Sgirish #else 178344961713Sgirish nxgep->rx_default_block_size = 0x2000; 178444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 178544961713Sgirish #endif 178644961713Sgirish /* 178744961713Sgirish * Get the system DMA burst size. 178844961713Sgirish */ 178944961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 179044961713Sgirish DDI_DMA_DONTWAIT, 0, 179144961713Sgirish &nxgep->dmasparehandle); 179244961713Sgirish if (ddi_status != DDI_SUCCESS) { 179344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 179444961713Sgirish "ddi_dma_alloc_handle: failed " 179544961713Sgirish " status 0x%x", ddi_status)); 179644961713Sgirish goto nxge_get_soft_properties_exit; 179744961713Sgirish } 179844961713Sgirish 179944961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 180044961713Sgirish (caddr_t)nxgep->dmasparehandle, 180144961713Sgirish sizeof (nxgep->dmasparehandle), 180244961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 180344961713Sgirish DDI_DMA_DONTWAIT, 0, 180444961713Sgirish &cookie, &count); 180544961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 180644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 180744961713Sgirish "Binding spare handle to find system" 180844961713Sgirish " burstsize failed.")); 180944961713Sgirish ddi_status = DDI_FAILURE; 181044961713Sgirish goto nxge_get_soft_properties_fail1; 181144961713Sgirish } 181244961713Sgirish 181344961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 181444961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 181544961713Sgirish 181644961713Sgirish nxge_get_soft_properties_fail1: 181744961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 181844961713Sgirish 181944961713Sgirish nxge_get_soft_properties_exit: 182044961713Sgirish 182144961713Sgirish if (ddi_status != DDI_SUCCESS) 182244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 182344961713Sgirish 182444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 182544961713Sgirish "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 182644961713Sgirish return (status); 182744961713Sgirish } 182844961713Sgirish 182944961713Sgirish static nxge_status_t 183044961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 183144961713Sgirish { 183244961713Sgirish nxge_status_t status = NXGE_OK; 183344961713Sgirish 183444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 183544961713Sgirish 183644961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 183744961713Sgirish if (status != NXGE_OK) { 183844961713Sgirish return (NXGE_ERROR); 183944961713Sgirish } 184044961713Sgirish 184144961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 184244961713Sgirish if (status != NXGE_OK) { 184344961713Sgirish nxge_free_rx_mem_pool(nxgep); 184444961713Sgirish return (NXGE_ERROR); 184544961713Sgirish } 184644961713Sgirish 184744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 184844961713Sgirish return (NXGE_OK); 184944961713Sgirish } 185044961713Sgirish 185144961713Sgirish static void 185244961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 185344961713Sgirish { 185444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 185544961713Sgirish 185644961713Sgirish nxge_free_rx_mem_pool(nxgep); 185744961713Sgirish nxge_free_tx_mem_pool(nxgep); 185844961713Sgirish 185944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 186044961713Sgirish } 186144961713Sgirish 186244961713Sgirish static nxge_status_t 186344961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 186444961713Sgirish { 186544961713Sgirish int i, j; 186644961713Sgirish uint32_t ndmas, st_rdc; 186744961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 186844961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 186944961713Sgirish p_nxge_dma_pool_t dma_poolp; 187044961713Sgirish p_nxge_dma_common_t *dma_buf_p; 187144961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 187244961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 187344961713Sgirish size_t rx_buf_alloc_size; 187444961713Sgirish size_t rx_cntl_alloc_size; 187544961713Sgirish uint32_t *num_chunks; /* per dma */ 187644961713Sgirish nxge_status_t status = NXGE_OK; 187744961713Sgirish 187844961713Sgirish uint32_t nxge_port_rbr_size; 187944961713Sgirish uint32_t nxge_port_rbr_spare_size; 188044961713Sgirish uint32_t nxge_port_rcr_size; 188144961713Sgirish 188244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 188344961713Sgirish 188444961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 188544961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 188644961713Sgirish st_rdc = p_cfgp->start_rdc; 188744961713Sgirish ndmas = p_cfgp->max_rdcs; 188844961713Sgirish 188944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 189044961713Sgirish " nxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 189144961713Sgirish 189244961713Sgirish /* 189344961713Sgirish * Allocate memory for each receive DMA channel. 189444961713Sgirish */ 189544961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 189644961713Sgirish KM_SLEEP); 189744961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 189844961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 189944961713Sgirish 190044961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 190144961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 190244961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 190344961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 190444961713Sgirish 190544961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 190644961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 190744961713Sgirish 190844961713Sgirish /* 190944961713Sgirish * Assume that each DMA channel will be configured with default 191044961713Sgirish * block size. 191144961713Sgirish * rbr block counts are mod of batch count (16). 191244961713Sgirish */ 191344961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 191444961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 191544961713Sgirish 191644961713Sgirish if (!nxge_port_rbr_size) { 191744961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 191844961713Sgirish } 191944961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 192044961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 192144961713Sgirish (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 192244961713Sgirish } 192344961713Sgirish 192444961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 192544961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 192644961713Sgirish 192744961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 192844961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 192944961713Sgirish (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 193044961713Sgirish } 193130ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 193230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 193330ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 193430ac2e7bSml "set to default %d", 193530ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 193630ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 193730ac2e7bSml } 193830ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 193930ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 194030ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 194130ac2e7bSml "set to default %d", 194230ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 194330ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 194430ac2e7bSml } 194544961713Sgirish 194644961713Sgirish /* 194744961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 194844961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 194944961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 195044961713Sgirish * function). 195144961713Sgirish */ 195244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 195344961713Sgirish if (nxgep->niu_type == N2_NIU) { 195444961713Sgirish nxge_port_rbr_spare_size = 0; 195544961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 195644961713Sgirish (!ISP2(nxge_port_rbr_size))) { 195744961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 195844961713Sgirish } 195944961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 196044961713Sgirish (!ISP2(nxge_port_rcr_size))) { 196144961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 196244961713Sgirish } 196344961713Sgirish } 196444961713Sgirish #endif 196544961713Sgirish 196644961713Sgirish rx_buf_alloc_size = (nxgep->rx_default_block_size * 196744961713Sgirish (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 196844961713Sgirish 196944961713Sgirish /* 197044961713Sgirish * Addresses of receive block ring, receive completion ring and the 197144961713Sgirish * mailbox must be all cache-aligned (64 bytes). 197244961713Sgirish */ 197344961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 197444961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 197544961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 197644961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 197744961713Sgirish 197844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 197944961713Sgirish "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 198044961713Sgirish "nxge_port_rcr_size = %d " 198144961713Sgirish "rx_cntl_alloc_size = %d", 198244961713Sgirish nxge_port_rbr_size, nxge_port_rbr_spare_size, 198344961713Sgirish nxge_port_rcr_size, 198444961713Sgirish rx_cntl_alloc_size)); 198544961713Sgirish 198644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 198744961713Sgirish if (nxgep->niu_type == N2_NIU) { 198844961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 198944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 199044961713Sgirish "==> nxge_alloc_rx_mem_pool: " 199144961713Sgirish " must be power of 2")); 199244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 199344961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 199444961713Sgirish } 199544961713Sgirish 199644961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 199744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 199844961713Sgirish "==> nxge_alloc_rx_mem_pool: " 199944961713Sgirish " limit size to 4M")); 200044961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 200144961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 200244961713Sgirish } 200344961713Sgirish 200444961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 200544961713Sgirish rx_cntl_alloc_size = 0x2000; 200644961713Sgirish } 200744961713Sgirish } 200844961713Sgirish #endif 200944961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 201044961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 201144961713Sgirish 201244961713Sgirish /* 201344961713Sgirish * Allocate memory for receive buffers and descriptor rings. 201444961713Sgirish * Replace allocation functions with interface functions provided 201544961713Sgirish * by the partition manager when it is available. 201644961713Sgirish */ 201744961713Sgirish /* 201844961713Sgirish * Allocate memory for the receive buffer blocks. 201944961713Sgirish */ 202044961713Sgirish for (i = 0; i < ndmas; i++) { 202144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 202244961713Sgirish " nxge_alloc_rx_mem_pool to alloc mem: " 202344961713Sgirish " dma %d dma_buf_p %llx &dma_buf_p %llx", 202444961713Sgirish i, dma_buf_p[i], &dma_buf_p[i])); 202544961713Sgirish num_chunks[i] = 0; 202644961713Sgirish status = nxge_alloc_rx_buf_dma(nxgep, st_rdc, &dma_buf_p[i], 202744961713Sgirish rx_buf_alloc_size, 202844961713Sgirish nxgep->rx_default_block_size, &num_chunks[i]); 202944961713Sgirish if (status != NXGE_OK) { 203044961713Sgirish break; 203144961713Sgirish } 203244961713Sgirish st_rdc++; 203344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 203444961713Sgirish " nxge_alloc_rx_mem_pool DONE alloc mem: " 203544961713Sgirish "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 203644961713Sgirish dma_buf_p[i], &dma_buf_p[i])); 203744961713Sgirish } 203844961713Sgirish if (i < ndmas) { 203944961713Sgirish goto nxge_alloc_rx_mem_fail1; 204044961713Sgirish } 204144961713Sgirish /* 204244961713Sgirish * Allocate memory for descriptor rings and mailbox. 204344961713Sgirish */ 204444961713Sgirish st_rdc = p_cfgp->start_rdc; 204544961713Sgirish for (j = 0; j < ndmas; j++) { 204644961713Sgirish status = nxge_alloc_rx_cntl_dma(nxgep, st_rdc, &dma_cntl_p[j], 204744961713Sgirish rx_cntl_alloc_size); 204844961713Sgirish if (status != NXGE_OK) { 204944961713Sgirish break; 205044961713Sgirish } 205144961713Sgirish st_rdc++; 205244961713Sgirish } 205344961713Sgirish if (j < ndmas) { 205444961713Sgirish goto nxge_alloc_rx_mem_fail2; 205544961713Sgirish } 205644961713Sgirish 205744961713Sgirish dma_poolp->ndmas = ndmas; 205844961713Sgirish dma_poolp->num_chunks = num_chunks; 205944961713Sgirish dma_poolp->buf_allocated = B_TRUE; 206044961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 206144961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 206244961713Sgirish 206344961713Sgirish dma_cntl_poolp->ndmas = ndmas; 206444961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 206544961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 206644961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 206744961713Sgirish 206844961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 206944961713Sgirish 207044961713Sgirish nxge_alloc_rx_mem_fail2: 207144961713Sgirish /* Free control buffers */ 207244961713Sgirish j--; 207344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 207444961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 207544961713Sgirish for (; j >= 0; j--) { 207644961713Sgirish nxge_free_rx_cntl_dma(nxgep, 207756d930aeSspeer (p_nxge_dma_common_t)dma_cntl_p[j]); 207844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 207944961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", 208044961713Sgirish j)); 208144961713Sgirish } 208244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 208344961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 208444961713Sgirish 208544961713Sgirish nxge_alloc_rx_mem_fail1: 208644961713Sgirish /* Free data buffers */ 208744961713Sgirish i--; 208844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 208944961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 209044961713Sgirish for (; i >= 0; i--) { 209144961713Sgirish nxge_free_rx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 209244961713Sgirish num_chunks[i]); 209344961713Sgirish } 209444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 209544961713Sgirish "==> nxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 209644961713Sgirish 209744961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 209844961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 209944961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 210044961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 210144961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 210244961713Sgirish 210344961713Sgirish nxge_alloc_rx_mem_pool_exit: 210444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 210544961713Sgirish "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 210644961713Sgirish 210744961713Sgirish return (status); 210844961713Sgirish } 210944961713Sgirish 211044961713Sgirish static void 211144961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 211244961713Sgirish { 211344961713Sgirish uint32_t i, ndmas; 211444961713Sgirish p_nxge_dma_pool_t dma_poolp; 211544961713Sgirish p_nxge_dma_common_t *dma_buf_p; 211644961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 211744961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 211844961713Sgirish uint32_t *num_chunks; 211944961713Sgirish 212044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 212144961713Sgirish 212244961713Sgirish dma_poolp = nxgep->rx_buf_pool_p; 212344961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 212444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 212544961713Sgirish "<== nxge_free_rx_mem_pool " 212644961713Sgirish "(null rx buf pool or buf not allocated")); 212744961713Sgirish return; 212844961713Sgirish } 212944961713Sgirish 213044961713Sgirish dma_cntl_poolp = nxgep->rx_cntl_pool_p; 213144961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 213244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 213344961713Sgirish "<== nxge_free_rx_mem_pool " 213444961713Sgirish "(null rx cntl buf pool or cntl buf not allocated")); 213544961713Sgirish return; 213644961713Sgirish } 213744961713Sgirish 213844961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 213944961713Sgirish num_chunks = dma_poolp->num_chunks; 214044961713Sgirish 214144961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 214244961713Sgirish ndmas = dma_cntl_poolp->ndmas; 214344961713Sgirish 214444961713Sgirish for (i = 0; i < ndmas; i++) { 214544961713Sgirish nxge_free_rx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 214644961713Sgirish } 214744961713Sgirish 214844961713Sgirish for (i = 0; i < ndmas; i++) { 214944961713Sgirish nxge_free_rx_cntl_dma(nxgep, dma_cntl_p[i]); 215044961713Sgirish } 215144961713Sgirish 215244961713Sgirish for (i = 0; i < ndmas; i++) { 215344961713Sgirish KMEM_FREE(dma_buf_p[i], 215444961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 215544961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 215644961713Sgirish } 215744961713Sgirish 215844961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 215944961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 216044961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 216144961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 216244961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 216344961713Sgirish 216444961713Sgirish nxgep->rx_buf_pool_p = NULL; 216544961713Sgirish nxgep->rx_cntl_pool_p = NULL; 216644961713Sgirish 216744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 216844961713Sgirish } 216944961713Sgirish 217044961713Sgirish 217144961713Sgirish static nxge_status_t 217244961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 217344961713Sgirish p_nxge_dma_common_t *dmap, 217444961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 217544961713Sgirish { 217644961713Sgirish p_nxge_dma_common_t rx_dmap; 217744961713Sgirish nxge_status_t status = NXGE_OK; 217844961713Sgirish size_t total_alloc_size; 217944961713Sgirish size_t allocated = 0; 218044961713Sgirish int i, size_index, array_size; 218144961713Sgirish 218244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 218344961713Sgirish 218444961713Sgirish rx_dmap = (p_nxge_dma_common_t) 218544961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 218644961713Sgirish KM_SLEEP); 218744961713Sgirish 218844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 218944961713Sgirish " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 219044961713Sgirish dma_channel, alloc_size, block_size, dmap)); 219144961713Sgirish 219244961713Sgirish total_alloc_size = alloc_size; 219344961713Sgirish 219444961713Sgirish #if defined(RX_USE_RECLAIM_POST) 219544961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 219644961713Sgirish #endif 219744961713Sgirish 219844961713Sgirish i = 0; 219944961713Sgirish size_index = 0; 220044961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 220144961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 220244961713Sgirish (size_index < array_size)) 220344961713Sgirish size_index++; 220444961713Sgirish if (size_index >= array_size) { 220544961713Sgirish size_index = array_size - 1; 220644961713Sgirish } 220744961713Sgirish 220844961713Sgirish while ((allocated < total_alloc_size) && 220944961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 221044961713Sgirish rx_dmap[i].dma_chunk_index = i; 221144961713Sgirish rx_dmap[i].block_size = block_size; 221244961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 221344961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 221444961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 221544961713Sgirish rx_dmap[i].dma_channel = dma_channel; 221644961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 221744961713Sgirish 221844961713Sgirish /* 221944961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 222044961713Sgirish * needs to call Hypervisor api to set up 222144961713Sgirish * logical pages. 222244961713Sgirish */ 222344961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 222444961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 222544961713Sgirish } 222644961713Sgirish 222744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 222844961713Sgirish "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 222944961713Sgirish "i %d nblocks %d alength %d", 223044961713Sgirish dma_channel, i, &rx_dmap[i], block_size, 223144961713Sgirish i, rx_dmap[i].nblocks, 223244961713Sgirish rx_dmap[i].alength)); 223344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 223444961713Sgirish &nxge_rx_dma_attr, 223544961713Sgirish rx_dmap[i].alength, 223644961713Sgirish &nxge_dev_buf_dma_acc_attr, 223744961713Sgirish DDI_DMA_READ | DDI_DMA_STREAMING, 223844961713Sgirish (p_nxge_dma_common_t)(&rx_dmap[i])); 223944961713Sgirish if (status != NXGE_OK) { 224044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 224144961713Sgirish " nxge_alloc_rx_buf_dma: Alloc Failed ")); 224244961713Sgirish size_index--; 224344961713Sgirish } else { 224444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 224544961713Sgirish " alloc_rx_buf_dma allocated rdc %d " 224644961713Sgirish "chunk %d size %x dvma %x bufp %llx ", 224744961713Sgirish dma_channel, i, rx_dmap[i].alength, 224844961713Sgirish rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 224944961713Sgirish i++; 225044961713Sgirish allocated += alloc_sizes[size_index]; 225144961713Sgirish } 225244961713Sgirish } 225344961713Sgirish 225444961713Sgirish 225544961713Sgirish if (allocated < total_alloc_size) { 225630ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 225730ac2e7bSml "==> nxge_alloc_rx_buf_dma: not enough for channe %d " 225830ac2e7bSml "allocated 0x%x requested 0x%x", 225930ac2e7bSml dma_channel, 226030ac2e7bSml allocated, total_alloc_size)); 226130ac2e7bSml status = NXGE_ERROR; 226244961713Sgirish goto nxge_alloc_rx_mem_fail1; 226344961713Sgirish } 226444961713Sgirish 226530ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 226630ac2e7bSml "==> nxge_alloc_rx_buf_dma: Allocated for channe %d " 226730ac2e7bSml "allocated 0x%x requested 0x%x", 226830ac2e7bSml dma_channel, 226930ac2e7bSml allocated, total_alloc_size)); 227030ac2e7bSml 227144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 227244961713Sgirish " alloc_rx_buf_dma rdc %d allocated %d chunks", 227344961713Sgirish dma_channel, i)); 227444961713Sgirish *num_chunks = i; 227544961713Sgirish *dmap = rx_dmap; 227644961713Sgirish 227744961713Sgirish goto nxge_alloc_rx_mem_exit; 227844961713Sgirish 227944961713Sgirish nxge_alloc_rx_mem_fail1: 228044961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 228144961713Sgirish 228244961713Sgirish nxge_alloc_rx_mem_exit: 228344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 228444961713Sgirish "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 228544961713Sgirish 228644961713Sgirish return (status); 228744961713Sgirish } 228844961713Sgirish 228944961713Sgirish /*ARGSUSED*/ 229044961713Sgirish static void 229144961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 229244961713Sgirish uint32_t num_chunks) 229344961713Sgirish { 229444961713Sgirish int i; 229544961713Sgirish 229644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 229744961713Sgirish "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 229844961713Sgirish 229944961713Sgirish for (i = 0; i < num_chunks; i++) { 230044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 230144961713Sgirish "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 230244961713Sgirish i, dmap)); 230344961713Sgirish nxge_dma_mem_free(dmap++); 230444961713Sgirish } 230544961713Sgirish 230644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 230744961713Sgirish } 230844961713Sgirish 230944961713Sgirish /*ARGSUSED*/ 231044961713Sgirish static nxge_status_t 231144961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 231244961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 231344961713Sgirish { 231444961713Sgirish p_nxge_dma_common_t rx_dmap; 231544961713Sgirish nxge_status_t status = NXGE_OK; 231644961713Sgirish 231744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 231844961713Sgirish 231944961713Sgirish rx_dmap = (p_nxge_dma_common_t) 232044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 232144961713Sgirish 232244961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 232344961713Sgirish 232444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 232544961713Sgirish &nxge_desc_dma_attr, 232644961713Sgirish size, 232744961713Sgirish &nxge_dev_desc_dma_acc_attr, 232844961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 232944961713Sgirish rx_dmap); 233044961713Sgirish if (status != NXGE_OK) { 233144961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 233244961713Sgirish } 233344961713Sgirish 233444961713Sgirish *dmap = rx_dmap; 233544961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 233644961713Sgirish 233744961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 233844961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 233944961713Sgirish 234044961713Sgirish nxge_alloc_rx_cntl_dma_exit: 234144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 234244961713Sgirish "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 234344961713Sgirish 234444961713Sgirish return (status); 234544961713Sgirish } 234644961713Sgirish 234744961713Sgirish /*ARGSUSED*/ 234844961713Sgirish static void 234944961713Sgirish nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 235044961713Sgirish { 235144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 235244961713Sgirish 235344961713Sgirish nxge_dma_mem_free(dmap); 235444961713Sgirish 235544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 235644961713Sgirish } 235744961713Sgirish 235844961713Sgirish static nxge_status_t 235944961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 236044961713Sgirish { 236144961713Sgirish nxge_status_t status = NXGE_OK; 236244961713Sgirish int i, j; 236344961713Sgirish uint32_t ndmas, st_tdc; 236444961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 236544961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 236644961713Sgirish p_nxge_dma_pool_t dma_poolp; 236744961713Sgirish p_nxge_dma_common_t *dma_buf_p; 236844961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 236944961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 237044961713Sgirish size_t tx_buf_alloc_size; 237144961713Sgirish size_t tx_cntl_alloc_size; 237244961713Sgirish uint32_t *num_chunks; /* per dma */ 23731f8914d5Sml uint32_t bcopy_thresh; 237444961713Sgirish 237544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 237644961713Sgirish 237744961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 237844961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 237944961713Sgirish st_tdc = p_cfgp->start_tdc; 238044961713Sgirish ndmas = p_cfgp->max_tdcs; 238144961713Sgirish 238244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool: " 238344961713Sgirish "p_cfgp 0x%016llx start_tdc %d ndmas %d nxgep->max_tdcs %d", 238444961713Sgirish p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, nxgep->max_tdcs)); 238544961713Sgirish /* 238644961713Sgirish * Allocate memory for each transmit DMA channel. 238744961713Sgirish */ 238844961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 238944961713Sgirish KM_SLEEP); 239044961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 239144961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 239244961713Sgirish 239344961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 239444961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 239544961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 239644961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 239744961713Sgirish 239830ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 239930ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 240030ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 240130ac2e7bSml "set to default %d", 240230ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 240330ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 240430ac2e7bSml } 240530ac2e7bSml 240644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 240744961713Sgirish /* 240844961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 240944961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 241044961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 241144961713Sgirish * function). The transmit ring is limited to 8K (includes the 241244961713Sgirish * mailbox). 241344961713Sgirish */ 241444961713Sgirish if (nxgep->niu_type == N2_NIU) { 241544961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 241644961713Sgirish (!ISP2(nxge_tx_ring_size))) { 241744961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 241844961713Sgirish } 241944961713Sgirish } 242044961713Sgirish #endif 242144961713Sgirish 242244961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 242344961713Sgirish 242444961713Sgirish /* 242544961713Sgirish * Assume that each DMA channel will be configured with default 242644961713Sgirish * transmit bufer size for copying transmit data. 242744961713Sgirish * (For packet payload over this limit, packets will not be 242844961713Sgirish * copied.) 242944961713Sgirish */ 24301f8914d5Sml if (nxgep->niu_type == N2_NIU) { 24311f8914d5Sml bcopy_thresh = TX_BCOPY_SIZE; 24321f8914d5Sml } else { 24331f8914d5Sml bcopy_thresh = nxge_bcopy_thresh; 24341f8914d5Sml } 24351f8914d5Sml tx_buf_alloc_size = (bcopy_thresh * nxge_tx_ring_size); 243644961713Sgirish 243744961713Sgirish /* 243844961713Sgirish * Addresses of transmit descriptor ring and the 243944961713Sgirish * mailbox must be all cache-aligned (64 bytes). 244044961713Sgirish */ 244144961713Sgirish tx_cntl_alloc_size = nxge_tx_ring_size; 244244961713Sgirish tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 244344961713Sgirish tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 244444961713Sgirish 244544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 244644961713Sgirish if (nxgep->niu_type == N2_NIU) { 244744961713Sgirish if (!ISP2(tx_buf_alloc_size)) { 244844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 244944961713Sgirish "==> nxge_alloc_tx_mem_pool: " 245044961713Sgirish " must be power of 2")); 245144961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 245244961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 245344961713Sgirish } 245444961713Sgirish 245544961713Sgirish if (tx_buf_alloc_size > (1 << 22)) { 245644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 245744961713Sgirish "==> nxge_alloc_tx_mem_pool: " 245844961713Sgirish " limit size to 4M")); 245944961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 246044961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 246144961713Sgirish } 246244961713Sgirish 246344961713Sgirish if (tx_cntl_alloc_size < 0x2000) { 246444961713Sgirish tx_cntl_alloc_size = 0x2000; 246544961713Sgirish } 246644961713Sgirish } 246744961713Sgirish #endif 246844961713Sgirish 246944961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 247044961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 247144961713Sgirish 247244961713Sgirish /* 247344961713Sgirish * Allocate memory for transmit buffers and descriptor rings. 247444961713Sgirish * Replace allocation functions with interface functions provided 247544961713Sgirish * by the partition manager when it is available. 247644961713Sgirish * 247744961713Sgirish * Allocate memory for the transmit buffer pool. 247844961713Sgirish */ 247944961713Sgirish for (i = 0; i < ndmas; i++) { 248044961713Sgirish num_chunks[i] = 0; 248144961713Sgirish status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i], 248244961713Sgirish tx_buf_alloc_size, 24831f8914d5Sml bcopy_thresh, &num_chunks[i]); 248444961713Sgirish if (status != NXGE_OK) { 248544961713Sgirish break; 248644961713Sgirish } 248744961713Sgirish st_tdc++; 248844961713Sgirish } 248944961713Sgirish if (i < ndmas) { 249044961713Sgirish goto nxge_alloc_tx_mem_pool_fail1; 249144961713Sgirish } 249244961713Sgirish 249344961713Sgirish st_tdc = p_cfgp->start_tdc; 249444961713Sgirish /* 249544961713Sgirish * Allocate memory for descriptor rings and mailbox. 249644961713Sgirish */ 249744961713Sgirish for (j = 0; j < ndmas; j++) { 249844961713Sgirish status = nxge_alloc_tx_cntl_dma(nxgep, st_tdc, &dma_cntl_p[j], 249944961713Sgirish tx_cntl_alloc_size); 250044961713Sgirish if (status != NXGE_OK) { 250144961713Sgirish break; 250244961713Sgirish } 250344961713Sgirish st_tdc++; 250444961713Sgirish } 250544961713Sgirish if (j < ndmas) { 250644961713Sgirish goto nxge_alloc_tx_mem_pool_fail2; 250744961713Sgirish } 250844961713Sgirish 250944961713Sgirish dma_poolp->ndmas = ndmas; 251044961713Sgirish dma_poolp->num_chunks = num_chunks; 251144961713Sgirish dma_poolp->buf_allocated = B_TRUE; 251244961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 251344961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 251444961713Sgirish 251544961713Sgirish dma_cntl_poolp->ndmas = ndmas; 251644961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 251744961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 251844961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 251944961713Sgirish 252044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 252144961713Sgirish "==> nxge_alloc_tx_mem_pool: start_tdc %d " 252244961713Sgirish "ndmas %d poolp->ndmas %d", 252344961713Sgirish st_tdc, ndmas, dma_poolp->ndmas)); 252444961713Sgirish 252544961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 252644961713Sgirish 252744961713Sgirish nxge_alloc_tx_mem_pool_fail2: 252844961713Sgirish /* Free control buffers */ 252944961713Sgirish j--; 253044961713Sgirish for (; j >= 0; j--) { 253144961713Sgirish nxge_free_tx_cntl_dma(nxgep, 253256d930aeSspeer (p_nxge_dma_common_t)dma_cntl_p[j]); 253344961713Sgirish } 253444961713Sgirish 253544961713Sgirish nxge_alloc_tx_mem_pool_fail1: 253644961713Sgirish /* Free data buffers */ 253744961713Sgirish i--; 253844961713Sgirish for (; i >= 0; i--) { 253944961713Sgirish nxge_free_tx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 254044961713Sgirish num_chunks[i]); 254144961713Sgirish } 254244961713Sgirish 254344961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 254444961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 254544961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 254644961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 254744961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 254844961713Sgirish 254944961713Sgirish nxge_alloc_tx_mem_pool_exit: 255044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 255144961713Sgirish "<== nxge_alloc_tx_mem_pool:status 0x%08x", status)); 255244961713Sgirish 255344961713Sgirish return (status); 255444961713Sgirish } 255544961713Sgirish 255644961713Sgirish static nxge_status_t 255744961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 255844961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 255944961713Sgirish size_t block_size, uint32_t *num_chunks) 256044961713Sgirish { 256144961713Sgirish p_nxge_dma_common_t tx_dmap; 256244961713Sgirish nxge_status_t status = NXGE_OK; 256344961713Sgirish size_t total_alloc_size; 256444961713Sgirish size_t allocated = 0; 256544961713Sgirish int i, size_index, array_size; 256644961713Sgirish 256744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 256844961713Sgirish 256944961713Sgirish tx_dmap = (p_nxge_dma_common_t) 257044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 257144961713Sgirish KM_SLEEP); 257244961713Sgirish 257344961713Sgirish total_alloc_size = alloc_size; 257444961713Sgirish i = 0; 257544961713Sgirish size_index = 0; 257644961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 257744961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 257844961713Sgirish (size_index < array_size)) 257944961713Sgirish size_index++; 258044961713Sgirish if (size_index >= array_size) { 258144961713Sgirish size_index = array_size - 1; 258244961713Sgirish } 258344961713Sgirish 258444961713Sgirish while ((allocated < total_alloc_size) && 258544961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 258644961713Sgirish 258744961713Sgirish tx_dmap[i].dma_chunk_index = i; 258844961713Sgirish tx_dmap[i].block_size = block_size; 258944961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 259044961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 259144961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 259244961713Sgirish tx_dmap[i].dma_channel = dma_channel; 259344961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 259444961713Sgirish 259544961713Sgirish /* 259644961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 259744961713Sgirish * needs to call Hypervisor api to set up 259844961713Sgirish * logical pages. 259944961713Sgirish */ 260044961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 260144961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 260244961713Sgirish } 260344961713Sgirish 260444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 260544961713Sgirish &nxge_tx_dma_attr, 260644961713Sgirish tx_dmap[i].alength, 260744961713Sgirish &nxge_dev_buf_dma_acc_attr, 260844961713Sgirish DDI_DMA_WRITE | DDI_DMA_STREAMING, 260944961713Sgirish (p_nxge_dma_common_t)(&tx_dmap[i])); 261044961713Sgirish if (status != NXGE_OK) { 261144961713Sgirish size_index--; 261244961713Sgirish } else { 261344961713Sgirish i++; 261444961713Sgirish allocated += alloc_sizes[size_index]; 261544961713Sgirish } 261644961713Sgirish } 261744961713Sgirish 261844961713Sgirish if (allocated < total_alloc_size) { 261930ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 262030ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 262130ac2e7bSml "allocated 0x%x requested 0x%x", 262230ac2e7bSml dma_channel, 262330ac2e7bSml allocated, total_alloc_size)); 262430ac2e7bSml status = NXGE_ERROR; 262544961713Sgirish goto nxge_alloc_tx_mem_fail1; 262644961713Sgirish } 262744961713Sgirish 262830ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 262930ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 263030ac2e7bSml "allocated 0x%x requested 0x%x", 263130ac2e7bSml dma_channel, 263230ac2e7bSml allocated, total_alloc_size)); 263330ac2e7bSml 263444961713Sgirish *num_chunks = i; 263544961713Sgirish *dmap = tx_dmap; 263644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 263744961713Sgirish "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 263844961713Sgirish *dmap, i)); 263944961713Sgirish goto nxge_alloc_tx_mem_exit; 264044961713Sgirish 264144961713Sgirish nxge_alloc_tx_mem_fail1: 264244961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 264344961713Sgirish 264444961713Sgirish nxge_alloc_tx_mem_exit: 264544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 264644961713Sgirish "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 264744961713Sgirish 264844961713Sgirish return (status); 264944961713Sgirish } 265044961713Sgirish 265144961713Sgirish /*ARGSUSED*/ 265244961713Sgirish static void 265344961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 265444961713Sgirish uint32_t num_chunks) 265544961713Sgirish { 265644961713Sgirish int i; 265744961713Sgirish 265844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 265944961713Sgirish 266044961713Sgirish for (i = 0; i < num_chunks; i++) { 266144961713Sgirish nxge_dma_mem_free(dmap++); 266244961713Sgirish } 266344961713Sgirish 266444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 266544961713Sgirish } 266644961713Sgirish 266744961713Sgirish /*ARGSUSED*/ 266844961713Sgirish static nxge_status_t 266944961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 267044961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 267144961713Sgirish { 267244961713Sgirish p_nxge_dma_common_t tx_dmap; 267344961713Sgirish nxge_status_t status = NXGE_OK; 267444961713Sgirish 267544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 267644961713Sgirish tx_dmap = (p_nxge_dma_common_t) 267744961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 267844961713Sgirish 267944961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 268044961713Sgirish 268144961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 268244961713Sgirish &nxge_desc_dma_attr, 268344961713Sgirish size, 268444961713Sgirish &nxge_dev_desc_dma_acc_attr, 268544961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 268644961713Sgirish tx_dmap); 268744961713Sgirish if (status != NXGE_OK) { 268844961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 268944961713Sgirish } 269044961713Sgirish 269144961713Sgirish *dmap = tx_dmap; 269244961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 269344961713Sgirish 269444961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 269544961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 269644961713Sgirish 269744961713Sgirish nxge_alloc_tx_cntl_dma_exit: 269844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 269944961713Sgirish "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 270044961713Sgirish 270144961713Sgirish return (status); 270244961713Sgirish } 270344961713Sgirish 270444961713Sgirish /*ARGSUSED*/ 270544961713Sgirish static void 270644961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 270744961713Sgirish { 270844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 270944961713Sgirish 271044961713Sgirish nxge_dma_mem_free(dmap); 271144961713Sgirish 271244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 271344961713Sgirish } 271444961713Sgirish 271544961713Sgirish static void 271644961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 271744961713Sgirish { 271844961713Sgirish uint32_t i, ndmas; 271944961713Sgirish p_nxge_dma_pool_t dma_poolp; 272044961713Sgirish p_nxge_dma_common_t *dma_buf_p; 272144961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 272244961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 272344961713Sgirish uint32_t *num_chunks; 272444961713Sgirish 272544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_free_tx_mem_pool")); 272644961713Sgirish 272744961713Sgirish dma_poolp = nxgep->tx_buf_pool_p; 272844961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 272944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 273044961713Sgirish "<== nxge_free_tx_mem_pool " 273144961713Sgirish "(null rx buf pool or buf not allocated")); 273244961713Sgirish return; 273344961713Sgirish } 273444961713Sgirish 273544961713Sgirish dma_cntl_poolp = nxgep->tx_cntl_pool_p; 273644961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 273744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 273844961713Sgirish "<== nxge_free_tx_mem_pool " 273944961713Sgirish "(null tx cntl buf pool or cntl buf not allocated")); 274044961713Sgirish return; 274144961713Sgirish } 274244961713Sgirish 274344961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 274444961713Sgirish num_chunks = dma_poolp->num_chunks; 274544961713Sgirish 274644961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 274744961713Sgirish ndmas = dma_cntl_poolp->ndmas; 274844961713Sgirish 274944961713Sgirish for (i = 0; i < ndmas; i++) { 275044961713Sgirish nxge_free_tx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 275144961713Sgirish } 275244961713Sgirish 275344961713Sgirish for (i = 0; i < ndmas; i++) { 275444961713Sgirish nxge_free_tx_cntl_dma(nxgep, dma_cntl_p[i]); 275544961713Sgirish } 275644961713Sgirish 275744961713Sgirish for (i = 0; i < ndmas; i++) { 275844961713Sgirish KMEM_FREE(dma_buf_p[i], 275944961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 276044961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 276144961713Sgirish } 276244961713Sgirish 276344961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 276444961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 276544961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 276644961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 276744961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 276844961713Sgirish 276944961713Sgirish nxgep->tx_buf_pool_p = NULL; 277044961713Sgirish nxgep->tx_cntl_pool_p = NULL; 277144961713Sgirish 277244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_free_tx_mem_pool")); 277344961713Sgirish } 277444961713Sgirish 277544961713Sgirish /*ARGSUSED*/ 277644961713Sgirish static nxge_status_t 277744961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 277844961713Sgirish struct ddi_dma_attr *dma_attrp, 277944961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 278044961713Sgirish p_nxge_dma_common_t dma_p) 278144961713Sgirish { 278244961713Sgirish caddr_t kaddrp; 278344961713Sgirish int ddi_status = DDI_SUCCESS; 278444961713Sgirish boolean_t contig_alloc_type; 278544961713Sgirish 278644961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 278744961713Sgirish 278844961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 278944961713Sgirish /* 279044961713Sgirish * contig_alloc_type for contiguous memory only allowed 279144961713Sgirish * for N2/NIU. 279244961713Sgirish */ 279344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 279444961713Sgirish "nxge_dma_mem_alloc: alloc type not allows (%d)", 279544961713Sgirish dma_p->contig_alloc_type)); 279644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 279744961713Sgirish } 279844961713Sgirish 279944961713Sgirish dma_p->dma_handle = NULL; 280044961713Sgirish dma_p->acc_handle = NULL; 280144961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 280244961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 280344961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 280444961713Sgirish DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 280544961713Sgirish if (ddi_status != DDI_SUCCESS) { 280644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280744961713Sgirish "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 280844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 280944961713Sgirish } 281044961713Sgirish 281144961713Sgirish switch (contig_alloc_type) { 281244961713Sgirish case B_FALSE: 281344961713Sgirish ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, 281444961713Sgirish acc_attr_p, 281544961713Sgirish xfer_flags, 281644961713Sgirish DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 281744961713Sgirish &dma_p->acc_handle); 281844961713Sgirish if (ddi_status != DDI_SUCCESS) { 281944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 282044961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 282144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 282244961713Sgirish dma_p->dma_handle = NULL; 282344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 282444961713Sgirish } 282544961713Sgirish if (dma_p->alength < length) { 282644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 282744961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 282844961713Sgirish "< length.")); 282944961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 283044961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 283144961713Sgirish dma_p->acc_handle = NULL; 283244961713Sgirish dma_p->dma_handle = NULL; 283344961713Sgirish return (NXGE_ERROR); 283444961713Sgirish } 283544961713Sgirish 283644961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 283744961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 283844961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 283944961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 284044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 284144961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 284244961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 284344961713Sgirish dma_p->ncookies)); 284444961713Sgirish if (dma_p->acc_handle) { 284544961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 284644961713Sgirish dma_p->acc_handle = NULL; 284744961713Sgirish } 284844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 284944961713Sgirish dma_p->dma_handle = NULL; 285044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 285144961713Sgirish } 285244961713Sgirish 285344961713Sgirish if (dma_p->ncookies != 1) { 285444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 285544961713Sgirish "nxge_dma_mem_alloc:ddi_dma_addr_bind " 285644961713Sgirish "> 1 cookie" 285744961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 285844961713Sgirish dma_p->ncookies)); 285944961713Sgirish if (dma_p->acc_handle) { 286044961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 286144961713Sgirish dma_p->acc_handle = NULL; 286244961713Sgirish } 286356d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 286444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 286544961713Sgirish dma_p->dma_handle = NULL; 286644961713Sgirish return (NXGE_ERROR); 286744961713Sgirish } 286844961713Sgirish break; 286944961713Sgirish 287044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 287144961713Sgirish case B_TRUE: 287244961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 287344961713Sgirish if (kaddrp == NULL) { 287444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 287544961713Sgirish "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 287644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 287744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 287844961713Sgirish } 287944961713Sgirish 288044961713Sgirish dma_p->alength = length; 288144961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 288244961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 288344961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 288444961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 288544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 288644961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 288744961713Sgirish "(status 0x%x ncookies %d.)", ddi_status, 288844961713Sgirish dma_p->ncookies)); 288944961713Sgirish 289044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 289144961713Sgirish "==> nxge_dma_mem_alloc: (not mapped)" 289244961713Sgirish "length %lu (0x%x) " 289344961713Sgirish "free contig kaddrp $%p " 289444961713Sgirish "va_to_pa $%p", 289544961713Sgirish length, length, 289644961713Sgirish kaddrp, 289744961713Sgirish va_to_pa(kaddrp))); 289844961713Sgirish 289944961713Sgirish 290044961713Sgirish contig_mem_free((void *)kaddrp, length); 290144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 290244961713Sgirish 290344961713Sgirish dma_p->dma_handle = NULL; 290444961713Sgirish dma_p->acc_handle = NULL; 290544961713Sgirish dma_p->alength = NULL; 290644961713Sgirish dma_p->kaddrp = NULL; 290744961713Sgirish 290844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 290944961713Sgirish } 291044961713Sgirish 291144961713Sgirish if (dma_p->ncookies != 1 || 291244961713Sgirish (dma_p->dma_cookie.dmac_laddress == NULL)) { 291344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 291444961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 291544961713Sgirish "cookie or " 291644961713Sgirish "dmac_laddress is NULL $%p size %d " 291744961713Sgirish " (status 0x%x ncookies %d.)", 291844961713Sgirish ddi_status, 291944961713Sgirish dma_p->dma_cookie.dmac_laddress, 292044961713Sgirish dma_p->dma_cookie.dmac_size, 292144961713Sgirish dma_p->ncookies)); 292244961713Sgirish 292344961713Sgirish contig_mem_free((void *)kaddrp, length); 292456d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 292544961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 292644961713Sgirish 292744961713Sgirish dma_p->alength = 0; 292844961713Sgirish dma_p->dma_handle = NULL; 292944961713Sgirish dma_p->acc_handle = NULL; 293044961713Sgirish dma_p->kaddrp = NULL; 293144961713Sgirish 293244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 293344961713Sgirish } 293444961713Sgirish break; 293544961713Sgirish 293644961713Sgirish #else 293744961713Sgirish case B_TRUE: 293844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 293944961713Sgirish "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 294044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 294144961713Sgirish #endif 294244961713Sgirish } 294344961713Sgirish 294444961713Sgirish dma_p->kaddrp = kaddrp; 294544961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 294644961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 2947adfcba55Sjoycey #if defined(__i386) 2948adfcba55Sjoycey dma_p->ioaddr_pp = 2949adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 2950adfcba55Sjoycey #else 295144961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 2952adfcba55Sjoycey #endif 295344961713Sgirish dma_p->last_ioaddr_pp = 2954adfcba55Sjoycey #if defined(__i386) 2955adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 2956adfcba55Sjoycey #else 295744961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress + 2958adfcba55Sjoycey #endif 295944961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 296044961713Sgirish 296144961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 296244961713Sgirish 296344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 296444961713Sgirish dma_p->orig_ioaddr_pp = 296544961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress; 296644961713Sgirish dma_p->orig_alength = length; 296744961713Sgirish dma_p->orig_kaddrp = kaddrp; 296844961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 296944961713Sgirish #endif 297044961713Sgirish 297144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 297244961713Sgirish "dma buffer allocated: dma_p $%p " 297344961713Sgirish "return dmac_ladress from cookie $%p cookie dmac_size %d " 297444961713Sgirish "dma_p->ioaddr_p $%p " 297544961713Sgirish "dma_p->orig_ioaddr_p $%p " 297644961713Sgirish "orig_vatopa $%p " 297744961713Sgirish "alength %d (0x%x) " 297844961713Sgirish "kaddrp $%p " 297944961713Sgirish "length %d (0x%x)", 298044961713Sgirish dma_p, 298144961713Sgirish dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 298244961713Sgirish dma_p->ioaddr_pp, 298344961713Sgirish dma_p->orig_ioaddr_pp, 298444961713Sgirish dma_p->orig_vatopa, 298544961713Sgirish dma_p->alength, dma_p->alength, 298644961713Sgirish kaddrp, 298744961713Sgirish length, length)); 298844961713Sgirish 298944961713Sgirish return (NXGE_OK); 299044961713Sgirish } 299144961713Sgirish 299244961713Sgirish static void 299344961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 299444961713Sgirish { 299544961713Sgirish if (dma_p->dma_handle != NULL) { 299644961713Sgirish if (dma_p->ncookies) { 299744961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 299844961713Sgirish dma_p->ncookies = 0; 299944961713Sgirish } 300044961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 300144961713Sgirish dma_p->dma_handle = NULL; 300244961713Sgirish } 300344961713Sgirish 300444961713Sgirish if (dma_p->acc_handle != NULL) { 300544961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 300644961713Sgirish dma_p->acc_handle = NULL; 300744961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 300844961713Sgirish } 300944961713Sgirish 301044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 301144961713Sgirish if (dma_p->contig_alloc_type && 301244961713Sgirish dma_p->orig_kaddrp && dma_p->orig_alength) { 301344961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 301444961713Sgirish "kaddrp $%p (orig_kaddrp $%p)" 301544961713Sgirish "mem type %d ", 301644961713Sgirish "orig_alength %d " 301744961713Sgirish "alength 0x%x (%d)", 301844961713Sgirish dma_p->kaddrp, 301944961713Sgirish dma_p->orig_kaddrp, 302044961713Sgirish dma_p->contig_alloc_type, 302144961713Sgirish dma_p->orig_alength, 302244961713Sgirish dma_p->alength, dma_p->alength)); 302344961713Sgirish 302444961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 302544961713Sgirish dma_p->orig_alength = NULL; 302644961713Sgirish dma_p->orig_kaddrp = NULL; 302744961713Sgirish dma_p->contig_alloc_type = B_FALSE; 302844961713Sgirish } 302944961713Sgirish #endif 303044961713Sgirish dma_p->kaddrp = NULL; 303144961713Sgirish dma_p->alength = NULL; 303244961713Sgirish } 303344961713Sgirish 303444961713Sgirish /* 303544961713Sgirish * nxge_m_start() -- start transmitting and receiving. 303644961713Sgirish * 303744961713Sgirish * This function is called by the MAC layer when the first 303844961713Sgirish * stream is open to prepare the hardware ready for sending 303944961713Sgirish * and transmitting packets. 304044961713Sgirish */ 304144961713Sgirish static int 304244961713Sgirish nxge_m_start(void *arg) 304344961713Sgirish { 304444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 304544961713Sgirish 304644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 304744961713Sgirish 304844961713Sgirish MUTEX_ENTER(nxgep->genlock); 304914ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 305044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 305144961713Sgirish "<== nxge_m_start: initialization failed")); 305244961713Sgirish MUTEX_EXIT(nxgep->genlock); 305344961713Sgirish return (EIO); 305444961713Sgirish } 305544961713Sgirish 305614ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 305714ea4bb7Ssd goto nxge_m_start_exit; 305844961713Sgirish /* 305944961713Sgirish * Start timer to check the system error and tx hangs 306044961713Sgirish */ 306144961713Sgirish nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state, 306244961713Sgirish NXGE_CHECK_TIMER); 306344961713Sgirish 3064a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3065a3c5bd6dSspeer 306644961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 306744961713Sgirish 306814ea4bb7Ssd nxge_m_start_exit: 306944961713Sgirish MUTEX_EXIT(nxgep->genlock); 307044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 307144961713Sgirish return (0); 307244961713Sgirish } 307344961713Sgirish 307444961713Sgirish /* 307544961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 307644961713Sgirish */ 307744961713Sgirish static void 307844961713Sgirish nxge_m_stop(void *arg) 307944961713Sgirish { 308044961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 308144961713Sgirish 308244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 308344961713Sgirish 308444961713Sgirish if (nxgep->nxge_timerid) { 308544961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 308644961713Sgirish nxgep->nxge_timerid = 0; 308744961713Sgirish } 3088a3c5bd6dSspeer 3089a3c5bd6dSspeer MUTEX_ENTER(nxgep->genlock); 309044961713Sgirish nxge_uninit(nxgep); 309144961713Sgirish 309244961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 309344961713Sgirish 309444961713Sgirish MUTEX_EXIT(nxgep->genlock); 309544961713Sgirish 309644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 309744961713Sgirish } 309844961713Sgirish 309944961713Sgirish static int 310044961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr) 310144961713Sgirish { 310244961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 310344961713Sgirish struct ether_addr addrp; 310444961713Sgirish 310544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst")); 310644961713Sgirish 310744961713Sgirish bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 310844961713Sgirish if (nxge_set_mac_addr(nxgep, &addrp)) { 310944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 311044961713Sgirish "<== nxge_m_unicst: set unitcast failed")); 311144961713Sgirish return (EINVAL); 311244961713Sgirish } 311344961713Sgirish 311444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst")); 311544961713Sgirish 311644961713Sgirish return (0); 311744961713Sgirish } 311844961713Sgirish 311944961713Sgirish static int 312044961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 312144961713Sgirish { 312244961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 312344961713Sgirish struct ether_addr addrp; 312444961713Sgirish 312544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 312644961713Sgirish "==> nxge_m_multicst: add %d", add)); 312744961713Sgirish 312844961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 312944961713Sgirish if (add) { 313044961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 313144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 313244961713Sgirish "<== nxge_m_multicst: add multicast failed")); 313344961713Sgirish return (EINVAL); 313444961713Sgirish } 313544961713Sgirish } else { 313644961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 313744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 313844961713Sgirish "<== nxge_m_multicst: del multicast failed")); 313944961713Sgirish return (EINVAL); 314044961713Sgirish } 314144961713Sgirish } 314244961713Sgirish 314344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 314444961713Sgirish 314544961713Sgirish return (0); 314644961713Sgirish } 314744961713Sgirish 314844961713Sgirish static int 314944961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 315044961713Sgirish { 315144961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 315244961713Sgirish 315344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 315444961713Sgirish "==> nxge_m_promisc: on %d", on)); 315544961713Sgirish 315644961713Sgirish if (nxge_set_promisc(nxgep, on)) { 315744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315844961713Sgirish "<== nxge_m_promisc: set promisc failed")); 315944961713Sgirish return (EINVAL); 316044961713Sgirish } 316144961713Sgirish 316244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 316344961713Sgirish "<== nxge_m_promisc: on %d", on)); 316444961713Sgirish 316544961713Sgirish return (0); 316644961713Sgirish } 316744961713Sgirish 316844961713Sgirish static void 316944961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 317044961713Sgirish { 317144961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 317256d930aeSspeer struct iocblk *iocp; 317344961713Sgirish boolean_t need_privilege; 317444961713Sgirish int err; 317544961713Sgirish int cmd; 317644961713Sgirish 317744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 317844961713Sgirish 317944961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 318044961713Sgirish iocp->ioc_error = 0; 318144961713Sgirish need_privilege = B_TRUE; 318244961713Sgirish cmd = iocp->ioc_cmd; 318344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 318444961713Sgirish switch (cmd) { 318544961713Sgirish default: 318644961713Sgirish miocnak(wq, mp, 0, EINVAL); 318744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 318844961713Sgirish return; 318944961713Sgirish 319044961713Sgirish case LB_GET_INFO_SIZE: 319144961713Sgirish case LB_GET_INFO: 319244961713Sgirish case LB_GET_MODE: 319344961713Sgirish need_privilege = B_FALSE; 319444961713Sgirish break; 319544961713Sgirish case LB_SET_MODE: 319644961713Sgirish break; 319744961713Sgirish 319844961713Sgirish case ND_GET: 319944961713Sgirish need_privilege = B_FALSE; 320044961713Sgirish break; 320144961713Sgirish case ND_SET: 320244961713Sgirish break; 320344961713Sgirish 320444961713Sgirish case NXGE_GET_MII: 320544961713Sgirish case NXGE_PUT_MII: 320644961713Sgirish case NXGE_GET64: 320744961713Sgirish case NXGE_PUT64: 320844961713Sgirish case NXGE_GET_TX_RING_SZ: 320944961713Sgirish case NXGE_GET_TX_DESC: 321044961713Sgirish case NXGE_TX_SIDE_RESET: 321144961713Sgirish case NXGE_RX_SIDE_RESET: 321244961713Sgirish case NXGE_GLOBAL_RESET: 321344961713Sgirish case NXGE_RESET_MAC: 321444961713Sgirish case NXGE_TX_REGS_DUMP: 321544961713Sgirish case NXGE_RX_REGS_DUMP: 321644961713Sgirish case NXGE_INT_REGS_DUMP: 321744961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 321844961713Sgirish case NXGE_PUT_TCAM: 321944961713Sgirish case NXGE_GET_TCAM: 322044961713Sgirish case NXGE_RTRACE: 322144961713Sgirish case NXGE_RDUMP: 322244961713Sgirish 322344961713Sgirish need_privilege = B_FALSE; 322444961713Sgirish break; 322544961713Sgirish case NXGE_INJECT_ERR: 322644961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 322744961713Sgirish nxge_err_inject(nxgep, wq, mp); 322844961713Sgirish break; 322944961713Sgirish } 323044961713Sgirish 323144961713Sgirish if (need_privilege) { 323256d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 323344961713Sgirish if (err != 0) { 323444961713Sgirish miocnak(wq, mp, 0, err); 323544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 323644961713Sgirish "<== nxge_m_ioctl: no priv")); 323744961713Sgirish return; 323844961713Sgirish } 323944961713Sgirish } 324044961713Sgirish 324144961713Sgirish switch (cmd) { 324244961713Sgirish case ND_GET: 324344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_GET command")); 324444961713Sgirish case ND_SET: 324544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_SET command")); 324644961713Sgirish nxge_param_ioctl(nxgep, wq, mp, iocp); 324744961713Sgirish break; 324844961713Sgirish 324944961713Sgirish case LB_GET_MODE: 325044961713Sgirish case LB_SET_MODE: 325144961713Sgirish case LB_GET_INFO_SIZE: 325244961713Sgirish case LB_GET_INFO: 325344961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 325444961713Sgirish break; 325544961713Sgirish 325644961713Sgirish case NXGE_GET_MII: 325744961713Sgirish case NXGE_PUT_MII: 325844961713Sgirish case NXGE_PUT_TCAM: 325944961713Sgirish case NXGE_GET_TCAM: 326044961713Sgirish case NXGE_GET64: 326144961713Sgirish case NXGE_PUT64: 326244961713Sgirish case NXGE_GET_TX_RING_SZ: 326344961713Sgirish case NXGE_GET_TX_DESC: 326444961713Sgirish case NXGE_TX_SIDE_RESET: 326544961713Sgirish case NXGE_RX_SIDE_RESET: 326644961713Sgirish case NXGE_GLOBAL_RESET: 326744961713Sgirish case NXGE_RESET_MAC: 326844961713Sgirish case NXGE_TX_REGS_DUMP: 326944961713Sgirish case NXGE_RX_REGS_DUMP: 327044961713Sgirish case NXGE_INT_REGS_DUMP: 327144961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 327244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 327344961713Sgirish "==> nxge_m_ioctl: cmd 0x%x", cmd)); 327444961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 327544961713Sgirish break; 327644961713Sgirish } 327744961713Sgirish 327844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 327944961713Sgirish } 328044961713Sgirish 328144961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 328244961713Sgirish 328344961713Sgirish static void 328444961713Sgirish nxge_m_resources(void *arg) 328544961713Sgirish { 328644961713Sgirish p_nxge_t nxgep = arg; 328744961713Sgirish mac_rx_fifo_t mrf; 328844961713Sgirish p_rx_rcr_rings_t rcr_rings; 328944961713Sgirish p_rx_rcr_ring_t *rcr_p; 329044961713Sgirish uint32_t i, ndmas; 329114ea4bb7Ssd nxge_status_t status; 329244961713Sgirish 329344961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources")); 329444961713Sgirish 329544961713Sgirish MUTEX_ENTER(nxgep->genlock); 329614ea4bb7Ssd 329714ea4bb7Ssd /* 329858324dfcSspeer * CR 6492541 Check to see if the drv_state has been initialized, 329914ea4bb7Ssd * if not * call nxge_init(). 330014ea4bb7Ssd */ 330114ea4bb7Ssd if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 330214ea4bb7Ssd status = nxge_init(nxgep); 330314ea4bb7Ssd if (status != NXGE_OK) 330414ea4bb7Ssd goto nxge_m_resources_exit; 330514ea4bb7Ssd } 330614ea4bb7Ssd 330744961713Sgirish mrf.mrf_type = MAC_RX_FIFO; 330844961713Sgirish mrf.mrf_blank = nxge_rx_hw_blank; 330944961713Sgirish mrf.mrf_arg = (void *)nxgep; 331044961713Sgirish 331144961713Sgirish mrf.mrf_normal_blank_time = 128; 331244961713Sgirish mrf.mrf_normal_pkt_count = 8; 331344961713Sgirish rcr_rings = nxgep->rx_rcr_rings; 331444961713Sgirish rcr_p = rcr_rings->rcr_rings; 331544961713Sgirish ndmas = rcr_rings->ndmas; 331644961713Sgirish 331714ea4bb7Ssd /* 331814ea4bb7Ssd * Export our receive resources to the MAC layer. 331914ea4bb7Ssd */ 332044961713Sgirish for (i = 0; i < ndmas; i++) { 332144961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle = 332244961713Sgirish mac_resource_add(nxgep->mach, 332344961713Sgirish (mac_resource_t *)&mrf); 332444961713Sgirish 332544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 332644961713Sgirish "==> nxge_m_resources: vdma %d dma %d " 332744961713Sgirish "rcrptr 0x%016llx mac_handle 0x%016llx", 332844961713Sgirish i, ((p_rx_rcr_ring_t)rcr_p[i])->rdc, 332944961713Sgirish rcr_p[i], 333044961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle)); 333144961713Sgirish } 333244961713Sgirish 333314ea4bb7Ssd nxge_m_resources_exit: 333444961713Sgirish MUTEX_EXIT(nxgep->genlock); 333544961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources")); 333644961713Sgirish } 333744961713Sgirish 333858324dfcSspeer static void 333958324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory) 334058324dfcSspeer { 334158324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 334258324dfcSspeer int i; 334358324dfcSspeer nxge_mmac_t *mmac_info; 334458324dfcSspeer 334558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 334658324dfcSspeer 334758324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 334858324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 334958324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 335058324dfcSspeer 335158324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 335258324dfcSspeer if (factory) { 335358324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 335458324dfcSspeer = mmac_info->factory_mac_pool[slot][(ETHERADDRL-1) - i]; 335558324dfcSspeer } else { 335658324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 335758324dfcSspeer = mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i]; 335858324dfcSspeer } 335958324dfcSspeer } 336058324dfcSspeer } 336158324dfcSspeer 336258324dfcSspeer /* 336358324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 336458324dfcSspeer */ 336558324dfcSspeer static int 336658324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot) 336758324dfcSspeer { 336858324dfcSspeer uint8_t addrn; 336958324dfcSspeer uint8_t portn; 337058324dfcSspeer npi_mac_addr_t altmac; 33717b9fa28bSspeer hostinfo_t mac_rdc; 33727b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 337358324dfcSspeer 337458324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 337558324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 337658324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 337758324dfcSspeer 337858324dfcSspeer portn = nxgep->mac.portnum; 337958324dfcSspeer addrn = (uint8_t)slot - 1; 338058324dfcSspeer 338158324dfcSspeer if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn, 338258324dfcSspeer addrn, &altmac) != NPI_SUCCESS) 338358324dfcSspeer return (EIO); 33847b9fa28bSspeer 33857b9fa28bSspeer /* 33867b9fa28bSspeer * Set the rdc table number for the host info entry 33877b9fa28bSspeer * for this mac address slot. 33887b9fa28bSspeer */ 33897b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 33907b9fa28bSspeer mac_rdc.value = 0; 33917b9fa28bSspeer mac_rdc.bits.w0.rdc_tbl_num = clscfgp->mac_host_info[addrn].rdctbl; 33927b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 33937b9fa28bSspeer 33947b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 33957b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 33967b9fa28bSspeer return (EIO); 33977b9fa28bSspeer } 33987b9fa28bSspeer 339958324dfcSspeer /* 340058324dfcSspeer * Enable comparison with the alternate MAC address. 340158324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 340258324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 340358324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 340458324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 340558324dfcSspeer */ 340658324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 340758324dfcSspeer addrn = (uint8_t)slot - 1; 340858324dfcSspeer else 340958324dfcSspeer addrn = (uint8_t)slot; 341058324dfcSspeer 341158324dfcSspeer if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn) 341258324dfcSspeer != NPI_SUCCESS) 341358324dfcSspeer return (EIO); 341458324dfcSspeer 341558324dfcSspeer return (0); 341658324dfcSspeer } 341758324dfcSspeer 341858324dfcSspeer /* 341958324dfcSspeer * nxeg_m_mmac_add() - find an unused address slot, set the address 342058324dfcSspeer * value to the one specified, enable the port to start filtering on 342158324dfcSspeer * the new MAC address. Returns 0 on success. 342258324dfcSspeer */ 342358324dfcSspeer static int 342458324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 342558324dfcSspeer { 342658324dfcSspeer p_nxge_t nxgep = arg; 342758324dfcSspeer mac_addr_slot_t slot; 342858324dfcSspeer nxge_mmac_t *mmac_info; 342958324dfcSspeer int err; 343058324dfcSspeer nxge_status_t status; 343158324dfcSspeer 343258324dfcSspeer mutex_enter(nxgep->genlock); 343358324dfcSspeer 343458324dfcSspeer /* 343558324dfcSspeer * Make sure that nxge is initialized, if _start() has 343658324dfcSspeer * not been called. 343758324dfcSspeer */ 343858324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 343958324dfcSspeer status = nxge_init(nxgep); 344058324dfcSspeer if (status != NXGE_OK) { 344158324dfcSspeer mutex_exit(nxgep->genlock); 344258324dfcSspeer return (ENXIO); 344358324dfcSspeer } 344458324dfcSspeer } 344558324dfcSspeer 344658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 344758324dfcSspeer if (mmac_info->naddrfree == 0) { 344858324dfcSspeer mutex_exit(nxgep->genlock); 344958324dfcSspeer return (ENOSPC); 345058324dfcSspeer } 345158324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 345258324dfcSspeer maddr->mma_addrlen)) { 345358324dfcSspeer mutex_exit(nxgep->genlock); 345458324dfcSspeer return (EINVAL); 345558324dfcSspeer } 345658324dfcSspeer /* 345758324dfcSspeer * Search for the first available slot. Because naddrfree 345858324dfcSspeer * is not zero, we are guaranteed to find one. 345958324dfcSspeer * Slot 0 is for unique (primary) MAC. The first alternate 346058324dfcSspeer * MAC slot is slot 1. 346158324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 346256d930aeSspeer * MAC slots but only the first 7 (or 15) slots have assigned factory 346358324dfcSspeer * MAC addresses. We first search among the slots without bundled 346458324dfcSspeer * factory MACs. If we fail to find one in that range, then we 346558324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 346658324dfcSspeer * will be wasted while the slot is used with a user MAC address. 346758324dfcSspeer * But the slot could be used by factory MAC again after calling 346858324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 346958324dfcSspeer */ 347058324dfcSspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 347158324dfcSspeer for (slot = mmac_info->num_factory_mmac + 1; 347258324dfcSspeer slot <= mmac_info->num_mmac; slot++) { 347358324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 347458324dfcSspeer break; 347558324dfcSspeer } 347658324dfcSspeer if (slot > mmac_info->num_mmac) { 347758324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 347858324dfcSspeer slot++) { 347958324dfcSspeer if (!(mmac_info->mac_pool[slot].flags 348058324dfcSspeer & MMAC_SLOT_USED)) 348158324dfcSspeer break; 348258324dfcSspeer } 348358324dfcSspeer } 348458324dfcSspeer } else { 348558324dfcSspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 348658324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 348758324dfcSspeer break; 348858324dfcSspeer } 348958324dfcSspeer } 349058324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 349158324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) { 349258324dfcSspeer mutex_exit(nxgep->genlock); 349358324dfcSspeer return (err); 349458324dfcSspeer } 349558324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 349658324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 349758324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 349858324dfcSspeer mmac_info->naddrfree--; 349958324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 350058324dfcSspeer 350158324dfcSspeer maddr->mma_slot = slot; 350258324dfcSspeer 350358324dfcSspeer mutex_exit(nxgep->genlock); 350458324dfcSspeer return (0); 350558324dfcSspeer } 350658324dfcSspeer 350758324dfcSspeer /* 350858324dfcSspeer * This function reserves an unused slot and programs the slot and the HW 350958324dfcSspeer * with a factory mac address. 351058324dfcSspeer */ 351158324dfcSspeer static int 351258324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr) 351358324dfcSspeer { 351458324dfcSspeer p_nxge_t nxgep = arg; 351558324dfcSspeer mac_addr_slot_t slot; 351658324dfcSspeer nxge_mmac_t *mmac_info; 351758324dfcSspeer int err; 351858324dfcSspeer nxge_status_t status; 351958324dfcSspeer 352058324dfcSspeer mutex_enter(nxgep->genlock); 352158324dfcSspeer 352258324dfcSspeer /* 352358324dfcSspeer * Make sure that nxge is initialized, if _start() has 352458324dfcSspeer * not been called. 352558324dfcSspeer */ 352658324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 352758324dfcSspeer status = nxge_init(nxgep); 352858324dfcSspeer if (status != NXGE_OK) { 352958324dfcSspeer mutex_exit(nxgep->genlock); 353058324dfcSspeer return (ENXIO); 353158324dfcSspeer } 353258324dfcSspeer } 353358324dfcSspeer 353458324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 353558324dfcSspeer if (mmac_info->naddrfree == 0) { 353658324dfcSspeer mutex_exit(nxgep->genlock); 353758324dfcSspeer return (ENOSPC); 353858324dfcSspeer } 353958324dfcSspeer 354058324dfcSspeer slot = maddr->mma_slot; 354158324dfcSspeer if (slot == -1) { /* -1: Take the first available slot */ 354258324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) { 354358324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 354458324dfcSspeer break; 354558324dfcSspeer } 354658324dfcSspeer if (slot > mmac_info->num_factory_mmac) { 354758324dfcSspeer mutex_exit(nxgep->genlock); 354858324dfcSspeer return (ENOSPC); 354958324dfcSspeer } 355058324dfcSspeer } 355158324dfcSspeer if (slot < 1 || slot > mmac_info->num_factory_mmac) { 355258324dfcSspeer /* 355358324dfcSspeer * Do not support factory MAC at a slot greater than 355458324dfcSspeer * num_factory_mmac even when there are available factory 355558324dfcSspeer * MAC addresses because the alternate MACs are bundled with 355658324dfcSspeer * slot[1] through slot[num_factory_mmac] 355758324dfcSspeer */ 355858324dfcSspeer mutex_exit(nxgep->genlock); 355958324dfcSspeer return (EINVAL); 356058324dfcSspeer } 356158324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 356258324dfcSspeer mutex_exit(nxgep->genlock); 356358324dfcSspeer return (EBUSY); 356458324dfcSspeer } 356558324dfcSspeer /* Verify the address to be reserved */ 356658324dfcSspeer if (!mac_unicst_verify(nxgep->mach, 356758324dfcSspeer mmac_info->factory_mac_pool[slot], ETHERADDRL)) { 356858324dfcSspeer mutex_exit(nxgep->genlock); 356958324dfcSspeer return (EINVAL); 357058324dfcSspeer } 357158324dfcSspeer if (err = nxge_altmac_set(nxgep, 357258324dfcSspeer mmac_info->factory_mac_pool[slot], slot)) { 357358324dfcSspeer mutex_exit(nxgep->genlock); 357458324dfcSspeer return (err); 357558324dfcSspeer } 357658324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL); 357758324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 357858324dfcSspeer mmac_info->naddrfree--; 357958324dfcSspeer 358058324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_TRUE); 358158324dfcSspeer mutex_exit(nxgep->genlock); 358258324dfcSspeer 358358324dfcSspeer /* Pass info back to the caller */ 358458324dfcSspeer maddr->mma_slot = slot; 358558324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 358658324dfcSspeer maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 358758324dfcSspeer 358858324dfcSspeer return (0); 358958324dfcSspeer } 359058324dfcSspeer 359158324dfcSspeer /* 359258324dfcSspeer * Remove the specified mac address and update the HW not to filter 359358324dfcSspeer * the mac address anymore. 359458324dfcSspeer */ 359558324dfcSspeer static int 359658324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 359758324dfcSspeer { 359858324dfcSspeer p_nxge_t nxgep = arg; 359958324dfcSspeer nxge_mmac_t *mmac_info; 360058324dfcSspeer uint8_t addrn; 360158324dfcSspeer uint8_t portn; 360258324dfcSspeer int err = 0; 360358324dfcSspeer nxge_status_t status; 360458324dfcSspeer 360558324dfcSspeer mutex_enter(nxgep->genlock); 360658324dfcSspeer 360758324dfcSspeer /* 360858324dfcSspeer * Make sure that nxge is initialized, if _start() has 360958324dfcSspeer * not been called. 361058324dfcSspeer */ 361158324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 361258324dfcSspeer status = nxge_init(nxgep); 361358324dfcSspeer if (status != NXGE_OK) { 361458324dfcSspeer mutex_exit(nxgep->genlock); 361558324dfcSspeer return (ENXIO); 361658324dfcSspeer } 361758324dfcSspeer } 361858324dfcSspeer 361958324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 362058324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 362158324dfcSspeer mutex_exit(nxgep->genlock); 362258324dfcSspeer return (EINVAL); 362358324dfcSspeer } 362458324dfcSspeer 362558324dfcSspeer portn = nxgep->mac.portnum; 362658324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 362758324dfcSspeer addrn = (uint8_t)slot - 1; 362858324dfcSspeer else 362958324dfcSspeer addrn = (uint8_t)slot; 363058324dfcSspeer 363158324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 363258324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 363358324dfcSspeer == NPI_SUCCESS) { 363458324dfcSspeer mmac_info->naddrfree++; 363558324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 363658324dfcSspeer /* 363758324dfcSspeer * Regardless if the MAC we just stopped filtering 363858324dfcSspeer * is a user addr or a facory addr, we must set 363958324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 364058324dfcSspeer * associated factory MAC to indicate that a factory 364158324dfcSspeer * MAC is available. 364258324dfcSspeer */ 364358324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 364458324dfcSspeer mmac_info->mac_pool[slot].flags 364558324dfcSspeer |= MMAC_VENDOR_ADDR; 364658324dfcSspeer } 364758324dfcSspeer /* 364858324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 364958324dfcSspeer * alternate MAC address if the slot is not used. 365058324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 365158324dfcSspeer * when the slot is not used!) 365258324dfcSspeer */ 365358324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 365458324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 365558324dfcSspeer } else { 365658324dfcSspeer err = EIO; 365758324dfcSspeer } 365858324dfcSspeer } else { 365958324dfcSspeer err = EINVAL; 366058324dfcSspeer } 366158324dfcSspeer 366258324dfcSspeer mutex_exit(nxgep->genlock); 366358324dfcSspeer return (err); 366458324dfcSspeer } 366558324dfcSspeer 366658324dfcSspeer 366758324dfcSspeer /* 366858324dfcSspeer * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve(). 366958324dfcSspeer */ 367058324dfcSspeer static int 367158324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 367258324dfcSspeer { 367358324dfcSspeer p_nxge_t nxgep = arg; 367458324dfcSspeer mac_addr_slot_t slot; 367558324dfcSspeer nxge_mmac_t *mmac_info; 367658324dfcSspeer int err = 0; 367758324dfcSspeer nxge_status_t status; 367858324dfcSspeer 367958324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 368058324dfcSspeer maddr->mma_addrlen)) 368158324dfcSspeer return (EINVAL); 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 if (slot < 1 || slot > mmac_info->num_mmac) { 370158324dfcSspeer mutex_exit(nxgep->genlock); 370258324dfcSspeer return (EINVAL); 370358324dfcSspeer } 370458324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 370558324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) 370658324dfcSspeer != 0) { 370758324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 370858324dfcSspeer ETHERADDRL); 370958324dfcSspeer /* 371058324dfcSspeer * Assume that the MAC passed down from the caller 371158324dfcSspeer * is not a factory MAC address (The user should 371258324dfcSspeer * call mmac_remove followed by mmac_reserve if 371358324dfcSspeer * he wants to use the factory MAC for this slot). 371458324dfcSspeer */ 371558324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 371658324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 371758324dfcSspeer } 371858324dfcSspeer } else { 371958324dfcSspeer err = EINVAL; 372058324dfcSspeer } 372158324dfcSspeer mutex_exit(nxgep->genlock); 372258324dfcSspeer return (err); 372358324dfcSspeer } 372458324dfcSspeer 372558324dfcSspeer /* 372658324dfcSspeer * nxge_m_mmac_get() - Get the MAC address and other information 372758324dfcSspeer * related to the slot. mma_flags should be set to 0 in the call. 372858324dfcSspeer * Note: although kstat shows MAC address as zero when a slot is 372958324dfcSspeer * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC 373058324dfcSspeer * to the caller as long as the slot is not using a user MAC address. 373158324dfcSspeer * The following table shows the rules, 373258324dfcSspeer * 373358324dfcSspeer * USED VENDOR mma_addr 373458324dfcSspeer * ------------------------------------------------------------ 373558324dfcSspeer * (1) Slot uses a user MAC: yes no user MAC 373658324dfcSspeer * (2) Slot uses a factory MAC: yes yes factory MAC 373758324dfcSspeer * (3) Slot is not used but is 373858324dfcSspeer * factory MAC capable: no yes factory MAC 373958324dfcSspeer * (4) Slot is not used and is 374058324dfcSspeer * not factory MAC capable: no no 0 374158324dfcSspeer * ------------------------------------------------------------ 374258324dfcSspeer */ 374358324dfcSspeer static int 374458324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 374558324dfcSspeer { 374658324dfcSspeer nxge_t *nxgep = arg; 374758324dfcSspeer mac_addr_slot_t slot; 374858324dfcSspeer nxge_mmac_t *mmac_info; 374958324dfcSspeer nxge_status_t status; 375058324dfcSspeer 375158324dfcSspeer slot = maddr->mma_slot; 375258324dfcSspeer 375358324dfcSspeer mutex_enter(nxgep->genlock); 375458324dfcSspeer 375558324dfcSspeer /* 375658324dfcSspeer * Make sure that nxge is initialized, if _start() has 375758324dfcSspeer * not been called. 375858324dfcSspeer */ 375958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 376058324dfcSspeer status = nxge_init(nxgep); 376158324dfcSspeer if (status != NXGE_OK) { 376258324dfcSspeer mutex_exit(nxgep->genlock); 376358324dfcSspeer return (ENXIO); 376458324dfcSspeer } 376558324dfcSspeer } 376658324dfcSspeer 376758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 376858324dfcSspeer 376958324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 377058324dfcSspeer mutex_exit(nxgep->genlock); 377158324dfcSspeer return (EINVAL); 377258324dfcSspeer } 377358324dfcSspeer maddr->mma_flags = 0; 377458324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) 377558324dfcSspeer maddr->mma_flags |= MMAC_SLOT_USED; 377658324dfcSspeer 377758324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) { 377858324dfcSspeer maddr->mma_flags |= MMAC_VENDOR_ADDR; 377958324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], 378058324dfcSspeer maddr->mma_addr, ETHERADDRL); 378158324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 378258324dfcSspeer } else { 378358324dfcSspeer if (maddr->mma_flags & MMAC_SLOT_USED) { 378458324dfcSspeer bcopy(mmac_info->mac_pool[slot].addr, 378558324dfcSspeer maddr->mma_addr, ETHERADDRL); 378658324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 378758324dfcSspeer } else { 378858324dfcSspeer bzero(maddr->mma_addr, ETHERADDRL); 378958324dfcSspeer maddr->mma_addrlen = 0; 379058324dfcSspeer } 379158324dfcSspeer } 379258324dfcSspeer mutex_exit(nxgep->genlock); 379358324dfcSspeer return (0); 379458324dfcSspeer } 379558324dfcSspeer 379658324dfcSspeer 379744961713Sgirish static boolean_t 379844961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 379944961713Sgirish { 380058324dfcSspeer nxge_t *nxgep = arg; 380158324dfcSspeer uint32_t *txflags = cap_data; 380258324dfcSspeer multiaddress_capab_t *mmacp = cap_data; 380344961713Sgirish 380458324dfcSspeer switch (cap) { 380558324dfcSspeer case MAC_CAPAB_HCKSUM: 380644961713Sgirish *txflags = HCKSUM_INET_PARTIAL; 380744961713Sgirish break; 380844961713Sgirish case MAC_CAPAB_POLL: 380944961713Sgirish /* 381044961713Sgirish * There's nothing for us to fill in, simply returning 381144961713Sgirish * B_TRUE stating that we support polling is sufficient. 381244961713Sgirish */ 381344961713Sgirish break; 381444961713Sgirish 381558324dfcSspeer case MAC_CAPAB_MULTIADDRESS: 381658324dfcSspeer mutex_enter(nxgep->genlock); 381758324dfcSspeer 381858324dfcSspeer mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac; 381958324dfcSspeer mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree; 382058324dfcSspeer mmacp->maddr_flag = 0; /* 0 is requried by PSARC2006/265 */ 382158324dfcSspeer /* 382258324dfcSspeer * maddr_handle is driver's private data, passed back to 382358324dfcSspeer * entry point functions as arg. 382458324dfcSspeer */ 382558324dfcSspeer mmacp->maddr_handle = nxgep; 382658324dfcSspeer mmacp->maddr_add = nxge_m_mmac_add; 382758324dfcSspeer mmacp->maddr_remove = nxge_m_mmac_remove; 382858324dfcSspeer mmacp->maddr_modify = nxge_m_mmac_modify; 382958324dfcSspeer mmacp->maddr_get = nxge_m_mmac_get; 383058324dfcSspeer mmacp->maddr_reserve = nxge_m_mmac_reserve; 383158324dfcSspeer 383258324dfcSspeer mutex_exit(nxgep->genlock); 383358324dfcSspeer break; 383430ac2e7bSml case MAC_CAPAB_LSO: { 383530ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 383630ac2e7bSml 38373d16f8e7Sml if (nxgep->soft_lso_enable) { 383830ac2e7bSml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 383930ac2e7bSml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 384030ac2e7bSml nxge_lso_max = NXGE_LSO_MAXLEN; 384130ac2e7bSml } 384230ac2e7bSml cap_lso->lso_basic_tcp_ipv4.lso_max = nxge_lso_max; 384330ac2e7bSml break; 384430ac2e7bSml } else { 384530ac2e7bSml return (B_FALSE); 384630ac2e7bSml } 384730ac2e7bSml } 384830ac2e7bSml 384944961713Sgirish default: 385044961713Sgirish return (B_FALSE); 385144961713Sgirish } 385244961713Sgirish return (B_TRUE); 385344961713Sgirish } 385444961713Sgirish 3855*1bd6825cSml static boolean_t 3856*1bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 3857*1bd6825cSml { 3858*1bd6825cSml /* 3859*1bd6825cSml * All adv_* parameters are locked (read-only) while 3860*1bd6825cSml * the device is in any sort of loopback mode ... 3861*1bd6825cSml */ 3862*1bd6825cSml switch (pr_num) { 3863*1bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 3864*1bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 3865*1bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 3866*1bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 3867*1bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 3868*1bd6825cSml case DLD_PROP_EN_100FDX_CAP: 3869*1bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 3870*1bd6825cSml case DLD_PROP_EN_100HDX_CAP: 3871*1bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 3872*1bd6825cSml case DLD_PROP_EN_10FDX_CAP: 3873*1bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 3874*1bd6825cSml case DLD_PROP_EN_10HDX_CAP: 3875*1bd6825cSml case DLD_PROP_AUTONEG: 3876*1bd6825cSml case DLD_PROP_FLOWCTRL: 3877*1bd6825cSml return (B_TRUE); 3878*1bd6825cSml } 3879*1bd6825cSml return (B_FALSE); 3880*1bd6825cSml } 3881*1bd6825cSml 3882*1bd6825cSml /* 3883*1bd6825cSml * callback functions for set/get of properties 3884*1bd6825cSml */ 3885*1bd6825cSml static int 3886*1bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 3887*1bd6825cSml uint_t pr_valsize, const void *pr_val) 3888*1bd6825cSml { 3889*1bd6825cSml nxge_t *nxgep = barg; 3890*1bd6825cSml p_nxge_param_t param_arr; 3891*1bd6825cSml p_nxge_stats_t statsp; 3892*1bd6825cSml int err = 0; 3893*1bd6825cSml uint8_t val; 3894*1bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 3895*1bd6825cSml link_flowctrl_t fl; 3896*1bd6825cSml 3897*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 3898*1bd6825cSml param_arr = nxgep->param_arr; 3899*1bd6825cSml statsp = nxgep->statsp; 3900*1bd6825cSml mutex_enter(nxgep->genlock); 3901*1bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 3902*1bd6825cSml nxge_param_locked(pr_num)) { 3903*1bd6825cSml /* 3904*1bd6825cSml * All adv_* parameters are locked (read-only) 3905*1bd6825cSml * while the device is in any sort of loopback mode. 3906*1bd6825cSml */ 3907*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 3908*1bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 3909*1bd6825cSml mutex_exit(nxgep->genlock); 3910*1bd6825cSml return (EBUSY); 3911*1bd6825cSml } 3912*1bd6825cSml 3913*1bd6825cSml val = *(uint8_t *)pr_val; 3914*1bd6825cSml switch (pr_num) { 3915*1bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 3916*1bd6825cSml nxgep->param_en_1000fdx = val; 3917*1bd6825cSml param_arr[param_anar_1000fdx].value = val; 3918*1bd6825cSml 3919*1bd6825cSml goto reprogram; 3920*1bd6825cSml 3921*1bd6825cSml case DLD_PROP_EN_100FDX_CAP: 3922*1bd6825cSml nxgep->param_en_100fdx = val; 3923*1bd6825cSml param_arr[param_anar_100fdx].value = val; 3924*1bd6825cSml 3925*1bd6825cSml goto reprogram; 3926*1bd6825cSml 3927*1bd6825cSml case DLD_PROP_EN_10FDX_CAP: 3928*1bd6825cSml nxgep->param_en_10fdx = val; 3929*1bd6825cSml param_arr[param_anar_10fdx].value = val; 3930*1bd6825cSml 3931*1bd6825cSml goto reprogram; 3932*1bd6825cSml 3933*1bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 3934*1bd6825cSml case DLD_PROP_EN_100HDX_CAP: 3935*1bd6825cSml case DLD_PROP_EN_10HDX_CAP: 3936*1bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 3937*1bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 3938*1bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 3939*1bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 3940*1bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 3941*1bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 3942*1bd6825cSml case DLD_PROP_STATUS: 3943*1bd6825cSml case DLD_PROP_SPEED: 3944*1bd6825cSml case DLD_PROP_DUPLEX: 3945*1bd6825cSml err = EINVAL; /* cannot set read-only properties */ 3946*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 3947*1bd6825cSml "==> nxge_m_setprop: read only property %d", 3948*1bd6825cSml pr_num)); 3949*1bd6825cSml break; 3950*1bd6825cSml 3951*1bd6825cSml case DLD_PROP_AUTONEG: 3952*1bd6825cSml param_arr[param_autoneg].value = val; 3953*1bd6825cSml 3954*1bd6825cSml goto reprogram; 3955*1bd6825cSml 3956*1bd6825cSml case DLD_PROP_DEFMTU: 3957*1bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 3958*1bd6825cSml err = EBUSY; 3959*1bd6825cSml break; 3960*1bd6825cSml } 3961*1bd6825cSml 3962*1bd6825cSml cur_mtu = nxgep->mac.default_mtu; 3963*1bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 3964*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 3965*1bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 3966*1bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 3967*1bd6825cSml 3968*1bd6825cSml if (new_mtu == cur_mtu) { 3969*1bd6825cSml err = 0; 3970*1bd6825cSml break; 3971*1bd6825cSml } 3972*1bd6825cSml if (new_mtu < NXGE_DEFAULT_MTU || 3973*1bd6825cSml new_mtu > NXGE_MAXIMUM_MTU) { 3974*1bd6825cSml err = EINVAL; 3975*1bd6825cSml break; 3976*1bd6825cSml } 3977*1bd6825cSml 3978*1bd6825cSml if ((new_mtu > NXGE_DEFAULT_MTU) && 3979*1bd6825cSml !nxgep->mac.is_jumbo) { 3980*1bd6825cSml err = EINVAL; 3981*1bd6825cSml break; 3982*1bd6825cSml } 3983*1bd6825cSml 3984*1bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 3985*1bd6825cSml nxgep->mac.maxframesize = (uint16_t) 3986*1bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 3987*1bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 3988*1bd6825cSml nxgep->mac.maxframesize = (uint16_t)old_framesize; 3989*1bd6825cSml err = EINVAL; 3990*1bd6825cSml break; 3991*1bd6825cSml } 3992*1bd6825cSml 3993*1bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 3994*1bd6825cSml if (err) { 3995*1bd6825cSml nxgep->mac.maxframesize = (uint16_t)old_framesize; 3996*1bd6825cSml err = EINVAL; 3997*1bd6825cSml break; 3998*1bd6825cSml } 3999*1bd6825cSml 4000*1bd6825cSml nxgep->mac.default_mtu = new_mtu; 4001*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4002*1bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 4003*1bd6825cSml new_mtu, nxgep->mac.maxframesize)); 4004*1bd6825cSml break; 4005*1bd6825cSml 4006*1bd6825cSml case DLD_PROP_FLOWCTRL: 4007*1bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 4008*1bd6825cSml switch (fl) { 4009*1bd6825cSml default: 4010*1bd6825cSml err = EINVAL; 4011*1bd6825cSml break; 4012*1bd6825cSml 4013*1bd6825cSml case LINK_FLOWCTRL_NONE: 4014*1bd6825cSml param_arr[param_anar_pause].value = 0; 4015*1bd6825cSml break; 4016*1bd6825cSml 4017*1bd6825cSml case LINK_FLOWCTRL_RX: 4018*1bd6825cSml param_arr[param_anar_pause].value = 1; 4019*1bd6825cSml break; 4020*1bd6825cSml 4021*1bd6825cSml case LINK_FLOWCTRL_TX: 4022*1bd6825cSml case LINK_FLOWCTRL_BI: 4023*1bd6825cSml err = EINVAL; 4024*1bd6825cSml break; 4025*1bd6825cSml } 4026*1bd6825cSml 4027*1bd6825cSml reprogram: 4028*1bd6825cSml if (err == 0) { 4029*1bd6825cSml if (!nxge_param_link_update(nxgep)) { 4030*1bd6825cSml err = EINVAL; 4031*1bd6825cSml } 4032*1bd6825cSml } 4033*1bd6825cSml break; 4034*1bd6825cSml 4035*1bd6825cSml default: 4036*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4037*1bd6825cSml "==> nxge_m_setprop: private property")); 4038*1bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 4039*1bd6825cSml pr_val); 4040*1bd6825cSml break; 4041*1bd6825cSml } 4042*1bd6825cSml 4043*1bd6825cSml mutex_exit(nxgep->genlock); 4044*1bd6825cSml 4045*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4046*1bd6825cSml "<== nxge_m_setprop (return %d)", err)); 4047*1bd6825cSml return (err); 4048*1bd6825cSml } 4049*1bd6825cSml 4050*1bd6825cSml static int 4051*1bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4052*1bd6825cSml uint_t pr_valsize, void *pr_val) 4053*1bd6825cSml { 4054*1bd6825cSml nxge_t *nxgep = barg; 4055*1bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 4056*1bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 4057*1bd6825cSml int err = 0; 4058*1bd6825cSml link_flowctrl_t fl; 4059*1bd6825cSml uint64_t tmp = 0; 4060*1bd6825cSml 4061*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4062*1bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 4063*1bd6825cSml bzero(pr_val, pr_valsize); 4064*1bd6825cSml switch (pr_num) { 4065*1bd6825cSml case DLD_PROP_DUPLEX: 4066*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4067*1bd6825cSml return (EINVAL); 4068*1bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 4069*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4070*1bd6825cSml "==> nxge_m_getprop: duplex mode %d", 4071*1bd6825cSml *(uint8_t *)pr_val)); 4072*1bd6825cSml break; 4073*1bd6825cSml 4074*1bd6825cSml case DLD_PROP_SPEED: 4075*1bd6825cSml if (pr_valsize < sizeof (uint64_t)) 4076*1bd6825cSml return (EINVAL); 4077*1bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 4078*1bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 4079*1bd6825cSml break; 4080*1bd6825cSml 4081*1bd6825cSml case DLD_PROP_STATUS: 4082*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4083*1bd6825cSml return (EINVAL); 4084*1bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_up; 4085*1bd6825cSml break; 4086*1bd6825cSml 4087*1bd6825cSml case DLD_PROP_AUTONEG: 4088*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4089*1bd6825cSml return (EINVAL); 4090*1bd6825cSml *(uint8_t *)pr_val = 4091*1bd6825cSml param_arr[param_autoneg].value; 4092*1bd6825cSml break; 4093*1bd6825cSml 4094*1bd6825cSml 4095*1bd6825cSml case DLD_PROP_DEFMTU: { 4096*1bd6825cSml if (pr_valsize < sizeof (uint64_t)) 4097*1bd6825cSml return (EINVAL); 4098*1bd6825cSml tmp = nxgep->mac.default_mtu; 4099*1bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 4100*1bd6825cSml break; 4101*1bd6825cSml } 4102*1bd6825cSml 4103*1bd6825cSml case DLD_PROP_FLOWCTRL: 4104*1bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 4105*1bd6825cSml return (EINVAL); 4106*1bd6825cSml 4107*1bd6825cSml fl = LINK_FLOWCTRL_NONE; 4108*1bd6825cSml if (param_arr[param_anar_pause].value) { 4109*1bd6825cSml fl = LINK_FLOWCTRL_RX; 4110*1bd6825cSml } 4111*1bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 4112*1bd6825cSml break; 4113*1bd6825cSml 4114*1bd6825cSml case DLD_PROP_ADV_1000FDX_CAP: 4115*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4116*1bd6825cSml return (EINVAL); 4117*1bd6825cSml *(uint8_t *)pr_val = 4118*1bd6825cSml param_arr[param_anar_1000fdx].value; 4119*1bd6825cSml break; 4120*1bd6825cSml 4121*1bd6825cSml case DLD_PROP_EN_1000FDX_CAP: 4122*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4123*1bd6825cSml return (EINVAL); 4124*1bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 4125*1bd6825cSml break; 4126*1bd6825cSml 4127*1bd6825cSml case DLD_PROP_ADV_100FDX_CAP: 4128*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4129*1bd6825cSml return (EINVAL); 4130*1bd6825cSml *(uint8_t *)pr_val = 4131*1bd6825cSml param_arr[param_anar_100fdx].value; 4132*1bd6825cSml break; 4133*1bd6825cSml 4134*1bd6825cSml case DLD_PROP_EN_100FDX_CAP: 4135*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4136*1bd6825cSml return (EINVAL); 4137*1bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 4138*1bd6825cSml break; 4139*1bd6825cSml 4140*1bd6825cSml case DLD_PROP_ADV_10FDX_CAP: 4141*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4142*1bd6825cSml return (EINVAL); 4143*1bd6825cSml *(uint8_t *)pr_val = 4144*1bd6825cSml param_arr[param_anar_10fdx].value; 4145*1bd6825cSml break; 4146*1bd6825cSml 4147*1bd6825cSml case DLD_PROP_EN_10FDX_CAP: 4148*1bd6825cSml if (pr_valsize < sizeof (uint8_t)) 4149*1bd6825cSml return (EINVAL); 4150*1bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 4151*1bd6825cSml break; 4152*1bd6825cSml 4153*1bd6825cSml case DLD_PROP_EN_1000HDX_CAP: 4154*1bd6825cSml case DLD_PROP_EN_100HDX_CAP: 4155*1bd6825cSml case DLD_PROP_EN_10HDX_CAP: 4156*1bd6825cSml case DLD_PROP_ADV_1000HDX_CAP: 4157*1bd6825cSml case DLD_PROP_ADV_100HDX_CAP: 4158*1bd6825cSml case DLD_PROP_ADV_10HDX_CAP: 4159*1bd6825cSml err = EINVAL; 4160*1bd6825cSml break; 4161*1bd6825cSml 4162*1bd6825cSml default: 4163*1bd6825cSml err = nxge_get_priv_prop(nxgep, pr_name, pr_valsize, 4164*1bd6825cSml pr_val); 4165*1bd6825cSml } 4166*1bd6825cSml 4167*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 4168*1bd6825cSml 4169*1bd6825cSml return (err); 4170*1bd6825cSml } 4171*1bd6825cSml 4172*1bd6825cSml /* ARGSUSED */ 4173*1bd6825cSml static int 4174*1bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 4175*1bd6825cSml const void *pr_val) 4176*1bd6825cSml { 4177*1bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 4178*1bd6825cSml int err = 0; 4179*1bd6825cSml long result; 4180*1bd6825cSml 4181*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4182*1bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 4183*1bd6825cSml 4184*1bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 4185*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4186*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4187*1bd6825cSml "<== nxge_set_priv_prop: name %s " 4188*1bd6825cSml "pr_val %s result %d " 4189*1bd6825cSml "param %d is_jumbo %d", 4190*1bd6825cSml pr_name, pr_val, result, 4191*1bd6825cSml param_arr[param_accept_jumbo].value, 4192*1bd6825cSml nxgep->mac.is_jumbo)); 4193*1bd6825cSml 4194*1bd6825cSml if (result > 1 || result < 0) { 4195*1bd6825cSml err = EINVAL; 4196*1bd6825cSml } else { 4197*1bd6825cSml if (nxgep->mac.is_jumbo == 4198*1bd6825cSml (uint32_t)result) { 4199*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4200*1bd6825cSml "no change (%d %d)", 4201*1bd6825cSml nxgep->mac.is_jumbo, 4202*1bd6825cSml result)); 4203*1bd6825cSml return (0); 4204*1bd6825cSml } 4205*1bd6825cSml } 4206*1bd6825cSml 4207*1bd6825cSml param_arr[param_accept_jumbo].value = result; 4208*1bd6825cSml nxgep->mac.is_jumbo = B_FALSE; 4209*1bd6825cSml if (result) { 4210*1bd6825cSml nxgep->mac.is_jumbo = B_TRUE; 4211*1bd6825cSml } 4212*1bd6825cSml 4213*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4214*1bd6825cSml "<== nxge_set_priv_prop: name %s (value %d) is_jumbo %d", 4215*1bd6825cSml pr_name, result, nxgep->mac.is_jumbo)); 4216*1bd6825cSml 4217*1bd6825cSml return (err); 4218*1bd6825cSml } 4219*1bd6825cSml 4220*1bd6825cSml /* Blanking */ 4221*1bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 4222*1bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 4223*1bd6825cSml (char *)pr_val, 4224*1bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 4225*1bd6825cSml if (err) { 4226*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4227*1bd6825cSml "<== nxge_set_priv_prop: " 4228*1bd6825cSml "unable to set (%s)", pr_name)); 4229*1bd6825cSml err = EINVAL; 4230*1bd6825cSml } else { 4231*1bd6825cSml err = 0; 4232*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4233*1bd6825cSml "<== nxge_set_priv_prop: " 4234*1bd6825cSml "set (%s)", pr_name)); 4235*1bd6825cSml } 4236*1bd6825cSml 4237*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4238*1bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 4239*1bd6825cSml pr_name, result)); 4240*1bd6825cSml 4241*1bd6825cSml return (err); 4242*1bd6825cSml } 4243*1bd6825cSml 4244*1bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 4245*1bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 4246*1bd6825cSml (char *)pr_val, 4247*1bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 4248*1bd6825cSml if (err) { 4249*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4250*1bd6825cSml "<== nxge_set_priv_prop: " 4251*1bd6825cSml "unable to set (%s)", pr_name)); 4252*1bd6825cSml err = EINVAL; 4253*1bd6825cSml } else { 4254*1bd6825cSml err = 0; 4255*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4256*1bd6825cSml "<== nxge_set_priv_prop: " 4257*1bd6825cSml "set (%s)", pr_name)); 4258*1bd6825cSml } 4259*1bd6825cSml 4260*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4261*1bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 4262*1bd6825cSml pr_name, result)); 4263*1bd6825cSml 4264*1bd6825cSml return (err); 4265*1bd6825cSml } 4266*1bd6825cSml 4267*1bd6825cSml /* Classification */ 4268*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 4269*1bd6825cSml if (pr_val == NULL) { 4270*1bd6825cSml err = EINVAL; 4271*1bd6825cSml return (err); 4272*1bd6825cSml } 4273*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4274*1bd6825cSml 4275*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4276*1bd6825cSml NULL, (char *)pr_val, 4277*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 4278*1bd6825cSml 4279*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4280*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4281*1bd6825cSml pr_name, result)); 4282*1bd6825cSml 4283*1bd6825cSml return (err); 4284*1bd6825cSml } 4285*1bd6825cSml 4286*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 4287*1bd6825cSml if (pr_val == NULL) { 4288*1bd6825cSml err = EINVAL; 4289*1bd6825cSml return (err); 4290*1bd6825cSml } 4291*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4292*1bd6825cSml 4293*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4294*1bd6825cSml NULL, (char *)pr_val, 4295*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 4296*1bd6825cSml 4297*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4298*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4299*1bd6825cSml pr_name, result)); 4300*1bd6825cSml 4301*1bd6825cSml return (err); 4302*1bd6825cSml } 4303*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 4304*1bd6825cSml if (pr_val == NULL) { 4305*1bd6825cSml err = EINVAL; 4306*1bd6825cSml return (err); 4307*1bd6825cSml } 4308*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4309*1bd6825cSml 4310*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4311*1bd6825cSml NULL, (char *)pr_val, 4312*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 4313*1bd6825cSml 4314*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4315*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4316*1bd6825cSml pr_name, result)); 4317*1bd6825cSml 4318*1bd6825cSml return (err); 4319*1bd6825cSml } 4320*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 4321*1bd6825cSml if (pr_val == NULL) { 4322*1bd6825cSml err = EINVAL; 4323*1bd6825cSml return (err); 4324*1bd6825cSml } 4325*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4326*1bd6825cSml 4327*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4328*1bd6825cSml NULL, (char *)pr_val, 4329*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 4330*1bd6825cSml 4331*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4332*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4333*1bd6825cSml pr_name, result)); 4334*1bd6825cSml 4335*1bd6825cSml return (err); 4336*1bd6825cSml } 4337*1bd6825cSml 4338*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 4339*1bd6825cSml if (pr_val == NULL) { 4340*1bd6825cSml err = EINVAL; 4341*1bd6825cSml return (err); 4342*1bd6825cSml } 4343*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4344*1bd6825cSml 4345*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4346*1bd6825cSml NULL, (char *)pr_val, 4347*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 4348*1bd6825cSml 4349*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4350*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4351*1bd6825cSml pr_name, result)); 4352*1bd6825cSml 4353*1bd6825cSml return (err); 4354*1bd6825cSml } 4355*1bd6825cSml 4356*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 4357*1bd6825cSml if (pr_val == NULL) { 4358*1bd6825cSml err = EINVAL; 4359*1bd6825cSml return (err); 4360*1bd6825cSml } 4361*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4362*1bd6825cSml 4363*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4364*1bd6825cSml NULL, (char *)pr_val, 4365*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 4366*1bd6825cSml 4367*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4368*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4369*1bd6825cSml pr_name, result)); 4370*1bd6825cSml 4371*1bd6825cSml return (err); 4372*1bd6825cSml } 4373*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 4374*1bd6825cSml if (pr_val == NULL) { 4375*1bd6825cSml err = EINVAL; 4376*1bd6825cSml return (err); 4377*1bd6825cSml } 4378*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4379*1bd6825cSml 4380*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4381*1bd6825cSml NULL, (char *)pr_val, 4382*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 4383*1bd6825cSml 4384*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4385*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4386*1bd6825cSml pr_name, result)); 4387*1bd6825cSml 4388*1bd6825cSml return (err); 4389*1bd6825cSml } 4390*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 4391*1bd6825cSml if (pr_val == NULL) { 4392*1bd6825cSml err = EINVAL; 4393*1bd6825cSml return (err); 4394*1bd6825cSml } 4395*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4396*1bd6825cSml 4397*1bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 4398*1bd6825cSml NULL, (char *)pr_val, 4399*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 4400*1bd6825cSml 4401*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4402*1bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 4403*1bd6825cSml pr_name, result)); 4404*1bd6825cSml 4405*1bd6825cSml return (err); 4406*1bd6825cSml } 4407*1bd6825cSml 4408*1bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 4409*1bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4410*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4411*1bd6825cSml "==> nxge_set_priv_prop: name %s (busy)", pr_name)); 4412*1bd6825cSml err = EBUSY; 4413*1bd6825cSml return (err); 4414*1bd6825cSml } 4415*1bd6825cSml if (pr_val == NULL) { 4416*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4417*1bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 4418*1bd6825cSml err = EINVAL; 4419*1bd6825cSml return (err); 4420*1bd6825cSml } 4421*1bd6825cSml 4422*1bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 4423*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4424*1bd6825cSml "<== nxge_set_priv_prop: name %s " 4425*1bd6825cSml "(lso %d pr_val %s value %d)", 4426*1bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 4427*1bd6825cSml 4428*1bd6825cSml if (result > 1 || result < 0) { 4429*1bd6825cSml err = EINVAL; 4430*1bd6825cSml } else { 4431*1bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 4432*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4433*1bd6825cSml "no change (%d %d)", 4434*1bd6825cSml nxgep->soft_lso_enable, result)); 4435*1bd6825cSml return (0); 4436*1bd6825cSml } 4437*1bd6825cSml } 4438*1bd6825cSml 4439*1bd6825cSml nxgep->soft_lso_enable = (int)result; 4440*1bd6825cSml 4441*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4442*1bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 4443*1bd6825cSml pr_name, result)); 4444*1bd6825cSml 4445*1bd6825cSml return (err); 4446*1bd6825cSml } 4447*1bd6825cSml 4448*1bd6825cSml return (EINVAL); 4449*1bd6825cSml } 4450*1bd6825cSml 4451*1bd6825cSml static int 4452*1bd6825cSml nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 4453*1bd6825cSml void *pr_val) 4454*1bd6825cSml { 4455*1bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 4456*1bd6825cSml char valstr[MAXNAMELEN]; 4457*1bd6825cSml int err = EINVAL; 4458*1bd6825cSml uint_t strsize; 4459*1bd6825cSml 4460*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4461*1bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 4462*1bd6825cSml 4463*1bd6825cSml /* function number */ 4464*1bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 4465*1bd6825cSml (void) sprintf(valstr, "%d", nxgep->function_num); 4466*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4467*1bd6825cSml "==> nxge_get_priv_prop: name %s " 4468*1bd6825cSml "(value %d valstr %s)", 4469*1bd6825cSml pr_name, nxgep->function_num, valstr)); 4470*1bd6825cSml 4471*1bd6825cSml err = 0; 4472*1bd6825cSml goto done; 4473*1bd6825cSml } 4474*1bd6825cSml 4475*1bd6825cSml /* Neptune firmware version */ 4476*1bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 4477*1bd6825cSml (void) sprintf(valstr, "%s", nxgep->vpd_info.ver); 4478*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4479*1bd6825cSml "==> nxge_get_priv_prop: name %s " 4480*1bd6825cSml "(value %d valstr %s)", 4481*1bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 4482*1bd6825cSml 4483*1bd6825cSml err = 0; 4484*1bd6825cSml goto done; 4485*1bd6825cSml } 4486*1bd6825cSml 4487*1bd6825cSml /* port PHY mode */ 4488*1bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 4489*1bd6825cSml switch (nxgep->mac.portmode) { 4490*1bd6825cSml case PORT_1G_COPPER: 4491*1bd6825cSml (void) sprintf(valstr, "1G copper %s", 4492*1bd6825cSml nxgep->hot_swappable_phy ? 4493*1bd6825cSml "[Hot Swappable]" : ""); 4494*1bd6825cSml break; 4495*1bd6825cSml case PORT_1G_FIBER: 4496*1bd6825cSml (void) sprintf(valstr, "1G fiber %s", 4497*1bd6825cSml nxgep->hot_swappable_phy ? 4498*1bd6825cSml "[hot swappable]" : ""); 4499*1bd6825cSml break; 4500*1bd6825cSml case PORT_10G_COPPER: 4501*1bd6825cSml (void) sprintf(valstr, "10G copper %s", 4502*1bd6825cSml nxgep->hot_swappable_phy ? 4503*1bd6825cSml "[hot swappable]" : ""); 4504*1bd6825cSml break; 4505*1bd6825cSml case PORT_10G_FIBER: 4506*1bd6825cSml (void) sprintf(valstr, "10G fiber %s", 4507*1bd6825cSml nxgep->hot_swappable_phy ? 4508*1bd6825cSml "[hot swappable]" : ""); 4509*1bd6825cSml break; 4510*1bd6825cSml case PORT_10G_SERDES: 4511*1bd6825cSml (void) sprintf(valstr, "10G serdes %s", 4512*1bd6825cSml nxgep->hot_swappable_phy ? 4513*1bd6825cSml "[hot swappable]" : ""); 4514*1bd6825cSml break; 4515*1bd6825cSml case PORT_1G_SERDES: 4516*1bd6825cSml (void) sprintf(valstr, "1G serdes %s", 4517*1bd6825cSml nxgep->hot_swappable_phy ? 4518*1bd6825cSml "[hot swappable]" : ""); 4519*1bd6825cSml break; 4520*1bd6825cSml case PORT_1G_RGMII_FIBER: 4521*1bd6825cSml (void) sprintf(valstr, "1G rgmii fiber %s", 4522*1bd6825cSml nxgep->hot_swappable_phy ? 4523*1bd6825cSml "[hot swappable]" : ""); 4524*1bd6825cSml break; 4525*1bd6825cSml case PORT_HSP_MODE: 4526*1bd6825cSml (void) sprintf(valstr, "phy not present[hot swappable]"); 4527*1bd6825cSml break; 4528*1bd6825cSml default: 4529*1bd6825cSml (void) sprintf(valstr, "unknown %s", 4530*1bd6825cSml nxgep->hot_swappable_phy ? 4531*1bd6825cSml "[hot swappable]" : ""); 4532*1bd6825cSml break; 4533*1bd6825cSml } 4534*1bd6825cSml 4535*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4536*1bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 4537*1bd6825cSml pr_name, valstr)); 4538*1bd6825cSml 4539*1bd6825cSml err = 0; 4540*1bd6825cSml goto done; 4541*1bd6825cSml } 4542*1bd6825cSml 4543*1bd6825cSml /* Hot swappable PHY */ 4544*1bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 4545*1bd6825cSml (void) sprintf(valstr, "%s", 4546*1bd6825cSml nxgep->hot_swappable_phy ? 4547*1bd6825cSml "yes" : "no"); 4548*1bd6825cSml 4549*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4550*1bd6825cSml "==> nxge_get_priv_prop: name %s " 4551*1bd6825cSml "(value %d valstr %s)", 4552*1bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 4553*1bd6825cSml 4554*1bd6825cSml err = 0; 4555*1bd6825cSml goto done; 4556*1bd6825cSml } 4557*1bd6825cSml 4558*1bd6825cSml 4559*1bd6825cSml /* accept jumbo */ 4560*1bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 4561*1bd6825cSml (void) sprintf(valstr, "%d", nxgep->mac.is_jumbo); 4562*1bd6825cSml err = 0; 4563*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4564*1bd6825cSml "==> nxge_get_priv_prop: name %s (value %d (%d, %d))", 4565*1bd6825cSml pr_name, 4566*1bd6825cSml (uint32_t)param_arr[param_accept_jumbo].value, 4567*1bd6825cSml nxgep->mac.is_jumbo, 4568*1bd6825cSml nxge_jumbo_enable)); 4569*1bd6825cSml 4570*1bd6825cSml goto done; 4571*1bd6825cSml } 4572*1bd6825cSml 4573*1bd6825cSml /* Receive Interrupt Blanking Parameters */ 4574*1bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 4575*1bd6825cSml (void) sprintf(valstr, "%d", nxgep->intr_timeout); 4576*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4577*1bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 4578*1bd6825cSml pr_name, 4579*1bd6825cSml (uint32_t)nxgep->intr_timeout)); 4580*1bd6825cSml err = 0; 4581*1bd6825cSml goto done; 4582*1bd6825cSml } 4583*1bd6825cSml 4584*1bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 4585*1bd6825cSml (void) sprintf(valstr, "%d", nxgep->intr_threshold); 4586*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4587*1bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 4588*1bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 4589*1bd6825cSml 4590*1bd6825cSml err = 0; 4591*1bd6825cSml goto done; 4592*1bd6825cSml } 4593*1bd6825cSml 4594*1bd6825cSml /* Classification and Load Distribution Configuration */ 4595*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 4596*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4597*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 4598*1bd6825cSml 4599*1bd6825cSml (void) sprintf(valstr, "%x", 4600*1bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 4601*1bd6825cSml 4602*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4603*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4604*1bd6825cSml goto done; 4605*1bd6825cSml } 4606*1bd6825cSml 4607*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 4608*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4609*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 4610*1bd6825cSml 4611*1bd6825cSml (void) sprintf(valstr, "%x", 4612*1bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 4613*1bd6825cSml 4614*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4615*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4616*1bd6825cSml goto done; 4617*1bd6825cSml } 4618*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 4619*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4620*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 4621*1bd6825cSml 4622*1bd6825cSml (void) sprintf(valstr, "%x", 4623*1bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 4624*1bd6825cSml 4625*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4626*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4627*1bd6825cSml goto done; 4628*1bd6825cSml } 4629*1bd6825cSml 4630*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 4631*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4632*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 4633*1bd6825cSml 4634*1bd6825cSml (void) printf(valstr, "%x", 4635*1bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 4636*1bd6825cSml 4637*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4638*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4639*1bd6825cSml goto done; 4640*1bd6825cSml } 4641*1bd6825cSml 4642*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 4643*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4644*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 4645*1bd6825cSml 4646*1bd6825cSml (void) sprintf(valstr, "%x", 4647*1bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 4648*1bd6825cSml 4649*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4650*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4651*1bd6825cSml err = 0; 4652*1bd6825cSml goto done; 4653*1bd6825cSml } 4654*1bd6825cSml 4655*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 4656*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4657*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 4658*1bd6825cSml 4659*1bd6825cSml (void) sprintf(valstr, "%x", 4660*1bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 4661*1bd6825cSml 4662*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4663*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4664*1bd6825cSml goto done; 4665*1bd6825cSml } 4666*1bd6825cSml 4667*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 4668*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4669*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 4670*1bd6825cSml 4671*1bd6825cSml (void) sprintf(valstr, "%x", 4672*1bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 4673*1bd6825cSml 4674*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4675*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4676*1bd6825cSml goto done; 4677*1bd6825cSml } 4678*1bd6825cSml 4679*1bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 4680*1bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 4681*1bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 4682*1bd6825cSml 4683*1bd6825cSml (void) sprintf(valstr, "%x", 4684*1bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 4685*1bd6825cSml 4686*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4687*1bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 4688*1bd6825cSml goto done; 4689*1bd6825cSml } 4690*1bd6825cSml 4691*1bd6825cSml /* Software LSO */ 4692*1bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 4693*1bd6825cSml (void) sprintf(valstr, "%d", nxgep->soft_lso_enable); 4694*1bd6825cSml err = 0; 4695*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4696*1bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 4697*1bd6825cSml pr_name, nxgep->soft_lso_enable)); 4698*1bd6825cSml 4699*1bd6825cSml goto done; 4700*1bd6825cSml } 4701*1bd6825cSml 4702*1bd6825cSml done: 4703*1bd6825cSml if (err == 0) { 4704*1bd6825cSml strsize = (uint_t)strlen(valstr); 4705*1bd6825cSml if (pr_valsize < strsize) { 4706*1bd6825cSml err = ENOBUFS; 4707*1bd6825cSml } else { 4708*1bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 4709*1bd6825cSml } 4710*1bd6825cSml } 4711*1bd6825cSml 4712*1bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4713*1bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 4714*1bd6825cSml return (err); 4715*1bd6825cSml } 4716*1bd6825cSml 471744961713Sgirish /* 471844961713Sgirish * Module loading and removing entry points. 471944961713Sgirish */ 472044961713Sgirish 472144961713Sgirish static struct cb_ops nxge_cb_ops = { 472244961713Sgirish nodev, /* cb_open */ 472344961713Sgirish nodev, /* cb_close */ 472444961713Sgirish nodev, /* cb_strategy */ 472544961713Sgirish nodev, /* cb_print */ 472644961713Sgirish nodev, /* cb_dump */ 472744961713Sgirish nodev, /* cb_read */ 472844961713Sgirish nodev, /* cb_write */ 472944961713Sgirish nodev, /* cb_ioctl */ 473044961713Sgirish nodev, /* cb_devmap */ 473144961713Sgirish nodev, /* cb_mmap */ 473244961713Sgirish nodev, /* cb_segmap */ 473344961713Sgirish nochpoll, /* cb_chpoll */ 473444961713Sgirish ddi_prop_op, /* cb_prop_op */ 473544961713Sgirish NULL, 473644961713Sgirish D_MP, /* cb_flag */ 473744961713Sgirish CB_REV, /* rev */ 473844961713Sgirish nodev, /* int (*cb_aread)() */ 473944961713Sgirish nodev /* int (*cb_awrite)() */ 474044961713Sgirish }; 474144961713Sgirish 474244961713Sgirish static struct dev_ops nxge_dev_ops = { 474344961713Sgirish DEVO_REV, /* devo_rev */ 474444961713Sgirish 0, /* devo_refcnt */ 474544961713Sgirish nulldev, 474658324dfcSspeer nulldev, /* devo_identify */ 474758324dfcSspeer nulldev, /* devo_probe */ 474858324dfcSspeer nxge_attach, /* devo_attach */ 474958324dfcSspeer nxge_detach, /* devo_detach */ 475058324dfcSspeer nodev, /* devo_reset */ 475158324dfcSspeer &nxge_cb_ops, /* devo_cb_ops */ 475258324dfcSspeer (struct bus_ops *)NULL, /* devo_bus_ops */ 475358324dfcSspeer ddi_power /* devo_power */ 475444961713Sgirish }; 475544961713Sgirish 475644961713Sgirish extern struct mod_ops mod_driverops; 475744961713Sgirish 47582e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 475944961713Sgirish 476044961713Sgirish /* 476144961713Sgirish * Module linkage information for the kernel. 476244961713Sgirish */ 476344961713Sgirish static struct modldrv nxge_modldrv = { 476444961713Sgirish &mod_driverops, 476544961713Sgirish NXGE_DESC_VER, 476644961713Sgirish &nxge_dev_ops 476744961713Sgirish }; 476844961713Sgirish 476944961713Sgirish static struct modlinkage modlinkage = { 477044961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 477144961713Sgirish }; 477244961713Sgirish 477344961713Sgirish int 477444961713Sgirish _init(void) 477544961713Sgirish { 477644961713Sgirish int status; 477744961713Sgirish 477844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 477944961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 478044961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 478144961713Sgirish if (status != 0) { 478244961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 478344961713Sgirish "failed to init device soft state")); 478444961713Sgirish goto _init_exit; 478544961713Sgirish } 478644961713Sgirish status = mod_install(&modlinkage); 478744961713Sgirish if (status != 0) { 478844961713Sgirish ddi_soft_state_fini(&nxge_list); 478944961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 479044961713Sgirish goto _init_exit; 479144961713Sgirish } 479244961713Sgirish 479344961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 479444961713Sgirish 479544961713Sgirish _init_exit: 479644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 479744961713Sgirish 479844961713Sgirish return (status); 479944961713Sgirish } 480044961713Sgirish 480144961713Sgirish int 480244961713Sgirish _fini(void) 480344961713Sgirish { 480444961713Sgirish int status; 480544961713Sgirish 480644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 480744961713Sgirish 480844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 4809a3c5bd6dSspeer 4810a3c5bd6dSspeer if (nxge_mblks_pending) 4811a3c5bd6dSspeer return (EBUSY); 4812a3c5bd6dSspeer 481344961713Sgirish status = mod_remove(&modlinkage); 481444961713Sgirish if (status != DDI_SUCCESS) { 481544961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 481644961713Sgirish "Module removal failed 0x%08x", 481744961713Sgirish status)); 481844961713Sgirish goto _fini_exit; 481944961713Sgirish } 482044961713Sgirish 482144961713Sgirish mac_fini_ops(&nxge_dev_ops); 482244961713Sgirish 482344961713Sgirish ddi_soft_state_fini(&nxge_list); 482444961713Sgirish 482544961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 482644961713Sgirish _fini_exit: 482744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 482844961713Sgirish 482944961713Sgirish return (status); 483044961713Sgirish } 483144961713Sgirish 483244961713Sgirish int 483344961713Sgirish _info(struct modinfo *modinfop) 483444961713Sgirish { 483544961713Sgirish int status; 483644961713Sgirish 483744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 483844961713Sgirish status = mod_info(&modlinkage, modinfop); 483944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 484044961713Sgirish 484144961713Sgirish return (status); 484244961713Sgirish } 484344961713Sgirish 484444961713Sgirish /*ARGSUSED*/ 484544961713Sgirish static nxge_status_t 484644961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 484744961713Sgirish { 484844961713Sgirish 484944961713Sgirish int intr_types; 485044961713Sgirish int type = 0; 485144961713Sgirish int ddi_status = DDI_SUCCESS; 485244961713Sgirish nxge_status_t status = NXGE_OK; 485344961713Sgirish 485444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 485544961713Sgirish 485644961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 485744961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 485844961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 485944961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 486044961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 486144961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 486244961713Sgirish 486344961713Sgirish if (nxgep->niu_type == N2_NIU) { 486444961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 486544961713Sgirish } else if (nxge_msi_enable) { 486644961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 486744961713Sgirish } 486844961713Sgirish 486944961713Sgirish /* Get the supported interrupt types */ 487044961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 487144961713Sgirish != DDI_SUCCESS) { 487244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 487344961713Sgirish "ddi_intr_get_supported_types failed: status 0x%08x", 487444961713Sgirish ddi_status)); 487544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 487644961713Sgirish } 487744961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 487844961713Sgirish 487944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 488044961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 488144961713Sgirish 488244961713Sgirish /* 488344961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 488444961713Sgirish * nxge_msi_enable (1): 488544961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 488644961713Sgirish */ 488744961713Sgirish switch (nxge_msi_enable) { 488844961713Sgirish default: 488944961713Sgirish type = DDI_INTR_TYPE_FIXED; 489044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 489144961713Sgirish "use fixed (intx emulation) type %08x", 489244961713Sgirish type)); 489344961713Sgirish break; 489444961713Sgirish 489544961713Sgirish case 2: 489644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 489744961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 489844961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 489944961713Sgirish type = DDI_INTR_TYPE_MSIX; 490044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 490144961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 490244961713Sgirish type)); 490344961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 490444961713Sgirish type = DDI_INTR_TYPE_MSI; 490544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 490644961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 490744961713Sgirish type)); 490844961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 490944961713Sgirish type = DDI_INTR_TYPE_FIXED; 491044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 491144961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 491244961713Sgirish type)); 491344961713Sgirish } 491444961713Sgirish break; 491544961713Sgirish 491644961713Sgirish case 1: 491744961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 491844961713Sgirish type = DDI_INTR_TYPE_MSI; 491944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 492044961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 492144961713Sgirish type)); 492244961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 492344961713Sgirish type = DDI_INTR_TYPE_MSIX; 492444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 492544961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 492644961713Sgirish type)); 492744961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 492844961713Sgirish type = DDI_INTR_TYPE_FIXED; 492944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 493044961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 493144961713Sgirish type)); 493244961713Sgirish } 493344961713Sgirish } 493444961713Sgirish 493544961713Sgirish nxgep->nxge_intr_type.intr_type = type; 493644961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 493744961713Sgirish type == DDI_INTR_TYPE_FIXED) && 493844961713Sgirish nxgep->nxge_intr_type.niu_msi_enable) { 493944961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 494044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 494144961713Sgirish " nxge_add_intrs: " 494244961713Sgirish " nxge_add_intrs_adv failed: status 0x%08x", 494344961713Sgirish status)); 494444961713Sgirish return (status); 494544961713Sgirish } else { 494644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 494744961713Sgirish "interrupts registered : type %d", type)); 494844961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 494944961713Sgirish 495044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 495144961713Sgirish "\nAdded advanced nxge add_intr_adv " 495244961713Sgirish "intr type 0x%x\n", type)); 495344961713Sgirish 495444961713Sgirish return (status); 495544961713Sgirish } 495644961713Sgirish } 495744961713Sgirish 495844961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 495944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 496044961713Sgirish "failed to register interrupts")); 496144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 496244961713Sgirish } 496344961713Sgirish 496444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 496544961713Sgirish return (status); 496644961713Sgirish } 496744961713Sgirish 496844961713Sgirish /*ARGSUSED*/ 496944961713Sgirish static nxge_status_t 497044961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep) 497144961713Sgirish { 497244961713Sgirish 497344961713Sgirish int ddi_status = DDI_SUCCESS; 497444961713Sgirish nxge_status_t status = NXGE_OK; 497544961713Sgirish 497644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs")); 497744961713Sgirish 497844961713Sgirish nxgep->resched_id = NULL; 497944961713Sgirish nxgep->resched_running = B_FALSE; 498044961713Sgirish ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW, 498144961713Sgirish &nxgep->resched_id, 498244961713Sgirish NULL, NULL, nxge_reschedule, (caddr_t)nxgep); 498344961713Sgirish if (ddi_status != DDI_SUCCESS) { 498444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: " 498544961713Sgirish "ddi_add_softintrs failed: status 0x%08x", 498644961713Sgirish ddi_status)); 498744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 498844961713Sgirish } 498944961713Sgirish 499044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs")); 499144961713Sgirish 499244961713Sgirish return (status); 499344961713Sgirish } 499444961713Sgirish 499544961713Sgirish static nxge_status_t 499644961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 499744961713Sgirish { 499844961713Sgirish int intr_type; 499944961713Sgirish p_nxge_intr_t intrp; 500044961713Sgirish 500144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 500244961713Sgirish 500344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 500444961713Sgirish intr_type = intrp->intr_type; 500544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 500644961713Sgirish intr_type)); 500744961713Sgirish 500844961713Sgirish switch (intr_type) { 500944961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 501044961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 501144961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 501244961713Sgirish 501344961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 501444961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 501544961713Sgirish 501644961713Sgirish default: 501744961713Sgirish return (NXGE_ERROR); 501844961713Sgirish } 501944961713Sgirish } 502044961713Sgirish 502144961713Sgirish 502244961713Sgirish /*ARGSUSED*/ 502344961713Sgirish static nxge_status_t 502444961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 502544961713Sgirish { 502644961713Sgirish dev_info_t *dip = nxgep->dip; 502744961713Sgirish p_nxge_ldg_t ldgp; 502844961713Sgirish p_nxge_intr_t intrp; 502944961713Sgirish uint_t *inthandler; 503044961713Sgirish void *arg1, *arg2; 503144961713Sgirish int behavior; 5032ec090658Sml int nintrs, navail, nrequest; 503344961713Sgirish int nactual, nrequired; 503444961713Sgirish int inum = 0; 503544961713Sgirish int x, y; 503644961713Sgirish int ddi_status = DDI_SUCCESS; 503744961713Sgirish nxge_status_t status = NXGE_OK; 503844961713Sgirish 503944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 504044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 504144961713Sgirish intrp->start_inum = 0; 504244961713Sgirish 504344961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 504444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 504544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 504644961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 504744961713Sgirish "nintrs: %d", ddi_status, nintrs)); 504844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 504944961713Sgirish } 505044961713Sgirish 505144961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 505244961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 505344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 505444961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 505544961713Sgirish "nintrs: %d", ddi_status, navail)); 505644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 505744961713Sgirish } 505844961713Sgirish 505944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 506044961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, navail %d", 506144961713Sgirish nintrs, navail)); 506244961713Sgirish 5063ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5064ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5065ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5066ec090658Sml if (nrequest < navail) { 5067ec090658Sml navail = nrequest; 5068ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5069ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5070ec090658Sml "navail %d (nrequest %d)", 5071ec090658Sml nintrs, navail, nrequest)); 5072ec090658Sml } 5073ec090658Sml } 5074ec090658Sml 507544961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 507644961713Sgirish /* MSI must be power of 2 */ 507744961713Sgirish if ((navail & 16) == 16) { 507844961713Sgirish navail = 16; 507944961713Sgirish } else if ((navail & 8) == 8) { 508044961713Sgirish navail = 8; 508144961713Sgirish } else if ((navail & 4) == 4) { 508244961713Sgirish navail = 4; 508344961713Sgirish } else if ((navail & 2) == 2) { 508444961713Sgirish navail = 2; 508544961713Sgirish } else { 508644961713Sgirish navail = 1; 508744961713Sgirish } 508844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 508944961713Sgirish "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 509044961713Sgirish "navail %d", nintrs, navail)); 509144961713Sgirish } 509244961713Sgirish 509344961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 509444961713Sgirish DDI_INTR_ALLOC_NORMAL); 509544961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 509644961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 509744961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 509844961713Sgirish navail, &nactual, behavior); 509944961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 510044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 510144961713Sgirish " ddi_intr_alloc() failed: %d", 510244961713Sgirish ddi_status)); 510344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 510444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 510544961713Sgirish } 510644961713Sgirish 510744961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 510844961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 510944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 511044961713Sgirish " ddi_intr_get_pri() failed: %d", 511144961713Sgirish ddi_status)); 511244961713Sgirish /* Free already allocated interrupts */ 511344961713Sgirish for (y = 0; y < nactual; y++) { 511444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 511544961713Sgirish } 511644961713Sgirish 511744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 511844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 511944961713Sgirish } 512044961713Sgirish 512144961713Sgirish nrequired = 0; 512244961713Sgirish switch (nxgep->niu_type) { 512344961713Sgirish default: 512444961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 512544961713Sgirish break; 512644961713Sgirish 512744961713Sgirish case N2_NIU: 512844961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 512944961713Sgirish break; 513044961713Sgirish } 513144961713Sgirish 513244961713Sgirish if (status != NXGE_OK) { 513344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 513444961713Sgirish "nxge_add_intrs_adv_typ:nxge_ldgv_init " 513544961713Sgirish "failed: 0x%x", status)); 513644961713Sgirish /* Free already allocated interrupts */ 513744961713Sgirish for (y = 0; y < nactual; y++) { 513844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 513944961713Sgirish } 514044961713Sgirish 514144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 514244961713Sgirish return (status); 514344961713Sgirish } 514444961713Sgirish 514544961713Sgirish ldgp = nxgep->ldgvp->ldgp; 514644961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 514744961713Sgirish ldgp->vector = (uint8_t)x; 514844961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 514944961713Sgirish arg1 = ldgp->ldvp; 515044961713Sgirish arg2 = nxgep; 515144961713Sgirish if (ldgp->nldvs == 1) { 515244961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 515344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 515444961713Sgirish "nxge_add_intrs_adv_type: " 515544961713Sgirish "arg1 0x%x arg2 0x%x: " 515644961713Sgirish "1-1 int handler (entry %d intdata 0x%x)\n", 515744961713Sgirish arg1, arg2, 515844961713Sgirish x, ldgp->intdata)); 515944961713Sgirish } else if (ldgp->nldvs > 1) { 516044961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 516144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 516244961713Sgirish "nxge_add_intrs_adv_type: " 516344961713Sgirish "arg1 0x%x arg2 0x%x: " 516444961713Sgirish "nldevs %d int handler " 516544961713Sgirish "(entry %d intdata 0x%x)\n", 516644961713Sgirish arg1, arg2, 516744961713Sgirish ldgp->nldvs, x, ldgp->intdata)); 516844961713Sgirish } 516944961713Sgirish 517044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 517144961713Sgirish "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 517244961713Sgirish "htable 0x%llx", x, intrp->htable[x])); 517344961713Sgirish 517444961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 517544961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 517644961713Sgirish != DDI_SUCCESS) { 517744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 517844961713Sgirish "==> nxge_add_intrs_adv_type: failed #%d " 517944961713Sgirish "status 0x%x", x, ddi_status)); 518044961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 518144961713Sgirish (void) ddi_intr_remove_handler( 518244961713Sgirish intrp->htable[y]); 518344961713Sgirish } 518444961713Sgirish /* Free already allocated intr */ 518544961713Sgirish for (y = 0; y < nactual; y++) { 518644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 518744961713Sgirish } 518844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 518944961713Sgirish 519044961713Sgirish (void) nxge_ldgv_uninit(nxgep); 519144961713Sgirish 519244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 519344961713Sgirish } 519444961713Sgirish intrp->intr_added++; 519544961713Sgirish } 519644961713Sgirish 519744961713Sgirish intrp->msi_intx_cnt = nactual; 519844961713Sgirish 519944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 520044961713Sgirish "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 520144961713Sgirish navail, nactual, 520244961713Sgirish intrp->msi_intx_cnt, 520344961713Sgirish intrp->intr_added)); 520444961713Sgirish 520544961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 520644961713Sgirish 520744961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 520844961713Sgirish 520944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 521044961713Sgirish 521144961713Sgirish return (status); 521244961713Sgirish } 521344961713Sgirish 521444961713Sgirish /*ARGSUSED*/ 521544961713Sgirish static nxge_status_t 521644961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 521744961713Sgirish { 521844961713Sgirish dev_info_t *dip = nxgep->dip; 521944961713Sgirish p_nxge_ldg_t ldgp; 522044961713Sgirish p_nxge_intr_t intrp; 522144961713Sgirish uint_t *inthandler; 522244961713Sgirish void *arg1, *arg2; 522344961713Sgirish int behavior; 522444961713Sgirish int nintrs, navail; 522544961713Sgirish int nactual, nrequired; 522644961713Sgirish int inum = 0; 522744961713Sgirish int x, y; 522844961713Sgirish int ddi_status = DDI_SUCCESS; 522944961713Sgirish nxge_status_t status = NXGE_OK; 523044961713Sgirish 523144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 523244961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 523344961713Sgirish intrp->start_inum = 0; 523444961713Sgirish 523544961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 523644961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 523744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 523844961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 523944961713Sgirish "nintrs: %d", status, nintrs)); 524044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 524144961713Sgirish } 524244961713Sgirish 524344961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 524444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 524544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 524644961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 524744961713Sgirish "nintrs: %d", ddi_status, navail)); 524844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 524944961713Sgirish } 525044961713Sgirish 525144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 525244961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 525344961713Sgirish nintrs, navail)); 525444961713Sgirish 525544961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 525644961713Sgirish DDI_INTR_ALLOC_NORMAL); 525744961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 525844961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 525944961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 526044961713Sgirish navail, &nactual, behavior); 526144961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 526244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 526344961713Sgirish " ddi_intr_alloc() failed: %d", 526444961713Sgirish ddi_status)); 526544961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 526644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 526744961713Sgirish } 526844961713Sgirish 526944961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 527044961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 527144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 527244961713Sgirish " ddi_intr_get_pri() failed: %d", 527344961713Sgirish ddi_status)); 527444961713Sgirish /* Free already allocated interrupts */ 527544961713Sgirish for (y = 0; y < nactual; y++) { 527644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 527744961713Sgirish } 527844961713Sgirish 527944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 528044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 528144961713Sgirish } 528244961713Sgirish 528344961713Sgirish nrequired = 0; 528444961713Sgirish switch (nxgep->niu_type) { 528544961713Sgirish default: 528644961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 528744961713Sgirish break; 528844961713Sgirish 528944961713Sgirish case N2_NIU: 529044961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 529144961713Sgirish break; 529244961713Sgirish } 529344961713Sgirish 529444961713Sgirish if (status != NXGE_OK) { 529544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 529644961713Sgirish "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 529744961713Sgirish "failed: 0x%x", status)); 529844961713Sgirish /* Free already allocated interrupts */ 529944961713Sgirish for (y = 0; y < nactual; y++) { 530044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 530144961713Sgirish } 530244961713Sgirish 530344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 530444961713Sgirish return (status); 530544961713Sgirish } 530644961713Sgirish 530744961713Sgirish ldgp = nxgep->ldgvp->ldgp; 530844961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 530944961713Sgirish ldgp->vector = (uint8_t)x; 531044961713Sgirish if (nxgep->niu_type != N2_NIU) { 531144961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 531244961713Sgirish } 531344961713Sgirish 531444961713Sgirish arg1 = ldgp->ldvp; 531544961713Sgirish arg2 = nxgep; 531644961713Sgirish if (ldgp->nldvs == 1) { 531744961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 531844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 531944961713Sgirish "nxge_add_intrs_adv_type_fix: " 532044961713Sgirish "1-1 int handler(%d) ldg %d ldv %d " 532144961713Sgirish "arg1 $%p arg2 $%p\n", 532244961713Sgirish x, ldgp->ldg, ldgp->ldvp->ldv, 532344961713Sgirish arg1, arg2)); 532444961713Sgirish } else if (ldgp->nldvs > 1) { 532544961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 532644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 532744961713Sgirish "nxge_add_intrs_adv_type_fix: " 532844961713Sgirish "shared ldv %d int handler(%d) ldv %d ldg %d" 532944961713Sgirish "arg1 0x%016llx arg2 0x%016llx\n", 533044961713Sgirish x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 533144961713Sgirish arg1, arg2)); 533244961713Sgirish } 533344961713Sgirish 533444961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 533544961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 533644961713Sgirish != DDI_SUCCESS) { 533744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 533844961713Sgirish "==> nxge_add_intrs_adv_type_fix: failed #%d " 533944961713Sgirish "status 0x%x", x, ddi_status)); 534044961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 534144961713Sgirish (void) ddi_intr_remove_handler( 534244961713Sgirish intrp->htable[y]); 534344961713Sgirish } 534444961713Sgirish for (y = 0; y < nactual; y++) { 534544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 534644961713Sgirish } 534744961713Sgirish /* Free already allocated intr */ 534844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 534944961713Sgirish 535044961713Sgirish (void) nxge_ldgv_uninit(nxgep); 535144961713Sgirish 535244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 535344961713Sgirish } 535444961713Sgirish intrp->intr_added++; 535544961713Sgirish } 535644961713Sgirish 535744961713Sgirish intrp->msi_intx_cnt = nactual; 535844961713Sgirish 535944961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 536044961713Sgirish 536144961713Sgirish status = nxge_intr_ldgv_init(nxgep); 536244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 536344961713Sgirish 536444961713Sgirish return (status); 536544961713Sgirish } 536644961713Sgirish 536744961713Sgirish static void 536844961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 536944961713Sgirish { 537044961713Sgirish int i, inum; 537144961713Sgirish p_nxge_intr_t intrp; 537244961713Sgirish 537344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 537444961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 537544961713Sgirish if (!intrp->intr_registered) { 537644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 537744961713Sgirish "<== nxge_remove_intrs: interrupts not registered")); 537844961713Sgirish return; 537944961713Sgirish } 538044961713Sgirish 538144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 538244961713Sgirish 538344961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 538444961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 538544961713Sgirish intrp->intr_added); 538644961713Sgirish } else { 538744961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 538844961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 538944961713Sgirish } 539044961713Sgirish } 539144961713Sgirish 539244961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 539344961713Sgirish if (intrp->htable[inum]) { 539444961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 539544961713Sgirish } 539644961713Sgirish } 539744961713Sgirish 539844961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 539944961713Sgirish if (intrp->htable[inum]) { 540044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 540144961713Sgirish "nxge_remove_intrs: ddi_intr_free inum %d " 540244961713Sgirish "msi_intx_cnt %d intr_added %d", 540344961713Sgirish inum, 540444961713Sgirish intrp->msi_intx_cnt, 540544961713Sgirish intrp->intr_added)); 540644961713Sgirish 540744961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 540844961713Sgirish } 540944961713Sgirish } 541044961713Sgirish 541144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 541244961713Sgirish intrp->intr_registered = B_FALSE; 541344961713Sgirish intrp->intr_enabled = B_FALSE; 541444961713Sgirish intrp->msi_intx_cnt = 0; 541544961713Sgirish intrp->intr_added = 0; 541644961713Sgirish 5417a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 5418a3c5bd6dSspeer 5419ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 5420ec090658Sml "#msix-request"); 5421ec090658Sml 542244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 542344961713Sgirish } 542444961713Sgirish 542544961713Sgirish /*ARGSUSED*/ 542644961713Sgirish static void 542744961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep) 542844961713Sgirish { 542944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs")); 543044961713Sgirish if (nxgep->resched_id) { 543144961713Sgirish ddi_remove_softintr(nxgep->resched_id); 543244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 543344961713Sgirish "==> nxge_remove_soft_intrs: removed")); 543444961713Sgirish nxgep->resched_id = NULL; 543544961713Sgirish } 543644961713Sgirish 543744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs")); 543844961713Sgirish } 543944961713Sgirish 544044961713Sgirish /*ARGSUSED*/ 544144961713Sgirish static void 544244961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 544344961713Sgirish { 544444961713Sgirish p_nxge_intr_t intrp; 544544961713Sgirish int i; 544644961713Sgirish int status; 544744961713Sgirish 544844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 544944961713Sgirish 545044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 545144961713Sgirish 545244961713Sgirish if (!intrp->intr_registered) { 545344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 545444961713Sgirish "interrupts are not registered")); 545544961713Sgirish return; 545644961713Sgirish } 545744961713Sgirish 545844961713Sgirish if (intrp->intr_enabled) { 545944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 546044961713Sgirish "<== nxge_intrs_enable: already enabled")); 546144961713Sgirish return; 546244961713Sgirish } 546344961713Sgirish 546444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 546544961713Sgirish status = ddi_intr_block_enable(intrp->htable, 546644961713Sgirish intrp->intr_added); 546744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 546844961713Sgirish "block enable - status 0x%x total inums #%d\n", 546944961713Sgirish status, intrp->intr_added)); 547044961713Sgirish } else { 547144961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 547244961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 547344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 547444961713Sgirish "ddi_intr_enable:enable - status 0x%x " 547544961713Sgirish "total inums %d enable inum #%d\n", 547644961713Sgirish status, intrp->intr_added, i)); 547744961713Sgirish if (status == DDI_SUCCESS) { 547844961713Sgirish intrp->intr_enabled = B_TRUE; 547944961713Sgirish } 548044961713Sgirish } 548144961713Sgirish } 548244961713Sgirish 548344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 548444961713Sgirish } 548544961713Sgirish 548644961713Sgirish /*ARGSUSED*/ 548744961713Sgirish static void 548844961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 548944961713Sgirish { 549044961713Sgirish p_nxge_intr_t intrp; 549144961713Sgirish int i; 549244961713Sgirish 549344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 549444961713Sgirish 549544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 549644961713Sgirish 549744961713Sgirish if (!intrp->intr_registered) { 549844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 549944961713Sgirish "interrupts are not registered")); 550044961713Sgirish return; 550144961713Sgirish } 550244961713Sgirish 550344961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 550444961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 550544961713Sgirish intrp->intr_added); 550644961713Sgirish } else { 550744961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 550844961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 550944961713Sgirish } 551044961713Sgirish } 551144961713Sgirish 551244961713Sgirish intrp->intr_enabled = B_FALSE; 551344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 551444961713Sgirish } 551544961713Sgirish 551644961713Sgirish static nxge_status_t 551744961713Sgirish nxge_mac_register(p_nxge_t nxgep) 551844961713Sgirish { 551944961713Sgirish mac_register_t *macp; 552044961713Sgirish int status; 552144961713Sgirish 552244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 552344961713Sgirish 552444961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 552544961713Sgirish return (NXGE_ERROR); 552644961713Sgirish 552744961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 552844961713Sgirish macp->m_driver = nxgep; 552944961713Sgirish macp->m_dip = nxgep->dip; 553044961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 553144961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 553244961713Sgirish macp->m_min_sdu = 0; 5533*1bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 5534*1bd6825cSml NXGE_EHEADER_VLAN_CRC; 5535*1bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 5536d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 553744961713Sgirish 5538*1bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5539*1bd6825cSml "==> nxge_mac_register: instance %d " 5540*1bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 5541*1bd6825cSml nxgep->instance, 5542*1bd6825cSml macp->m_max_sdu, macp->m_margin, 5543*1bd6825cSml nxgep->mac.maxframesize, 5544*1bd6825cSml NXGE_EHEADER_VLAN_CRC)); 5545*1bd6825cSml 554644961713Sgirish status = mac_register(macp, &nxgep->mach); 554744961713Sgirish mac_free(macp); 554844961713Sgirish 554944961713Sgirish if (status != 0) { 555044961713Sgirish cmn_err(CE_WARN, 555144961713Sgirish "!nxge_mac_register failed (status %d instance %d)", 555244961713Sgirish status, nxgep->instance); 555344961713Sgirish return (NXGE_ERROR); 555444961713Sgirish } 555544961713Sgirish 555644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 555744961713Sgirish "(instance %d)", nxgep->instance)); 555844961713Sgirish 555944961713Sgirish return (NXGE_OK); 556044961713Sgirish } 556144961713Sgirish 556244961713Sgirish void 556344961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 556444961713Sgirish { 556544961713Sgirish ssize_t size; 556644961713Sgirish mblk_t *nmp; 556744961713Sgirish uint8_t blk_id; 556844961713Sgirish uint8_t chan; 556944961713Sgirish uint32_t err_id; 557044961713Sgirish err_inject_t *eip; 557144961713Sgirish 557244961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 557344961713Sgirish 557444961713Sgirish size = 1024; 557544961713Sgirish nmp = mp->b_cont; 557644961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 557744961713Sgirish blk_id = eip->blk_id; 557844961713Sgirish err_id = eip->err_id; 557944961713Sgirish chan = eip->chan; 558044961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 558144961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 558244961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 558344961713Sgirish switch (blk_id) { 558444961713Sgirish case MAC_BLK_ID: 558544961713Sgirish break; 558644961713Sgirish case TXMAC_BLK_ID: 558744961713Sgirish break; 558844961713Sgirish case RXMAC_BLK_ID: 558944961713Sgirish break; 559044961713Sgirish case MIF_BLK_ID: 559144961713Sgirish break; 559244961713Sgirish case IPP_BLK_ID: 559344961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 559444961713Sgirish break; 559544961713Sgirish case TXC_BLK_ID: 559644961713Sgirish nxge_txc_inject_err(nxgep, err_id); 559744961713Sgirish break; 559844961713Sgirish case TXDMA_BLK_ID: 559944961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 560044961713Sgirish break; 560144961713Sgirish case RXDMA_BLK_ID: 560244961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 560344961713Sgirish break; 560444961713Sgirish case ZCP_BLK_ID: 560544961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 560644961713Sgirish break; 560744961713Sgirish case ESPC_BLK_ID: 560844961713Sgirish break; 560944961713Sgirish case FFLP_BLK_ID: 561044961713Sgirish break; 561144961713Sgirish case PHY_BLK_ID: 561244961713Sgirish break; 561344961713Sgirish case ETHER_SERDES_BLK_ID: 561444961713Sgirish break; 561544961713Sgirish case PCIE_SERDES_BLK_ID: 561644961713Sgirish break; 561744961713Sgirish case VIR_BLK_ID: 561844961713Sgirish break; 561944961713Sgirish } 562044961713Sgirish 562144961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 562244961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 562344961713Sgirish 562444961713Sgirish miocack(wq, mp, (int)size, 0); 562544961713Sgirish } 562644961713Sgirish 562744961713Sgirish static int 562844961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 562944961713Sgirish { 563044961713Sgirish p_nxge_hw_list_t hw_p; 563144961713Sgirish dev_info_t *p_dip; 563244961713Sgirish 563344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 563444961713Sgirish 563544961713Sgirish p_dip = nxgep->p_dip; 563644961713Sgirish MUTEX_ENTER(&nxge_common_lock); 563744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 563844961713Sgirish "==> nxge_init_common_dev:func # %d", 563944961713Sgirish nxgep->function_num)); 564044961713Sgirish /* 564144961713Sgirish * Loop through existing per neptune hardware list. 564244961713Sgirish */ 564344961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 564444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 564544961713Sgirish "==> nxge_init_common_device:func # %d " 564644961713Sgirish "hw_p $%p parent dip $%p", 564744961713Sgirish nxgep->function_num, 564844961713Sgirish hw_p, 564944961713Sgirish p_dip)); 565044961713Sgirish if (hw_p->parent_devp == p_dip) { 565144961713Sgirish nxgep->nxge_hw_p = hw_p; 565244961713Sgirish hw_p->ndevs++; 565344961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 565444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 565544961713Sgirish "==> nxge_init_common_device:func # %d " 565644961713Sgirish "hw_p $%p parent dip $%p " 565744961713Sgirish "ndevs %d (found)", 565844961713Sgirish nxgep->function_num, 565944961713Sgirish hw_p, 566044961713Sgirish p_dip, 566144961713Sgirish hw_p->ndevs)); 566244961713Sgirish break; 566344961713Sgirish } 566444961713Sgirish } 566544961713Sgirish 566644961713Sgirish if (hw_p == NULL) { 566744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 566844961713Sgirish "==> nxge_init_common_device:func # %d " 566944961713Sgirish "parent dip $%p (new)", 567044961713Sgirish nxgep->function_num, 567144961713Sgirish p_dip)); 567244961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 567344961713Sgirish hw_p->parent_devp = p_dip; 567444961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 567544961713Sgirish nxgep->nxge_hw_p = hw_p; 567644961713Sgirish hw_p->ndevs++; 567744961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 567844961713Sgirish hw_p->next = nxge_hw_list; 567959ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 568059ac0c16Sdavemq hw_p->niu_type = N2_NIU; 568159ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 568259ac0c16Sdavemq } else { 568359ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 56842e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 568559ac0c16Sdavemq } 568644961713Sgirish 568744961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 568844961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 568944961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 569044961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 569144961713Sgirish 569244961713Sgirish nxge_hw_list = hw_p; 569359ac0c16Sdavemq 569459ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 569544961713Sgirish } 569644961713Sgirish 569744961713Sgirish MUTEX_EXIT(&nxge_common_lock); 569859ac0c16Sdavemq 56992e59129aSraghus nxgep->platform_type = hw_p->platform_type; 570059ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 570159ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 570259ac0c16Sdavemq } 570359ac0c16Sdavemq 570444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 570544961713Sgirish "==> nxge_init_common_device (nxge_hw_list) $%p", 570644961713Sgirish nxge_hw_list)); 570744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 570844961713Sgirish 570944961713Sgirish return (NXGE_OK); 571044961713Sgirish } 571144961713Sgirish 571244961713Sgirish static void 571344961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 571444961713Sgirish { 571544961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 571644961713Sgirish dev_info_t *p_dip; 571744961713Sgirish 571844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 571944961713Sgirish if (nxgep->nxge_hw_p == NULL) { 572044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 572144961713Sgirish "<== nxge_uninit_common_device (no common)")); 572244961713Sgirish return; 572344961713Sgirish } 572444961713Sgirish 572544961713Sgirish MUTEX_ENTER(&nxge_common_lock); 572644961713Sgirish h_hw_p = nxge_hw_list; 572744961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 572844961713Sgirish p_dip = hw_p->parent_devp; 572944961713Sgirish if (nxgep->nxge_hw_p == hw_p && 573044961713Sgirish p_dip == nxgep->p_dip && 573144961713Sgirish nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 573244961713Sgirish hw_p->magic == NXGE_NEPTUNE_MAGIC) { 573344961713Sgirish 573444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 573544961713Sgirish "==> nxge_uninit_common_device:func # %d " 573644961713Sgirish "hw_p $%p parent dip $%p " 573744961713Sgirish "ndevs %d (found)", 573844961713Sgirish nxgep->function_num, 573944961713Sgirish hw_p, 574044961713Sgirish p_dip, 574144961713Sgirish hw_p->ndevs)); 574244961713Sgirish 574344961713Sgirish nxgep->nxge_hw_p = NULL; 574444961713Sgirish if (hw_p->ndevs) { 574544961713Sgirish hw_p->ndevs--; 574644961713Sgirish } 574744961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 574844961713Sgirish if (!hw_p->ndevs) { 574944961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 575044961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 575144961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 575244961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 575344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 575444961713Sgirish "==> nxge_uninit_common_device: " 575544961713Sgirish "func # %d " 575644961713Sgirish "hw_p $%p parent dip $%p " 575744961713Sgirish "ndevs %d (last)", 575844961713Sgirish nxgep->function_num, 575944961713Sgirish hw_p, 576044961713Sgirish p_dip, 576144961713Sgirish hw_p->ndevs)); 576244961713Sgirish 576344961713Sgirish if (hw_p == nxge_hw_list) { 576444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 576544961713Sgirish "==> nxge_uninit_common_device:" 576644961713Sgirish "remove head func # %d " 576744961713Sgirish "hw_p $%p parent dip $%p " 576844961713Sgirish "ndevs %d (head)", 576944961713Sgirish nxgep->function_num, 577044961713Sgirish hw_p, 577144961713Sgirish p_dip, 577244961713Sgirish hw_p->ndevs)); 577344961713Sgirish nxge_hw_list = hw_p->next; 577444961713Sgirish } else { 577544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 577644961713Sgirish "==> nxge_uninit_common_device:" 577744961713Sgirish "remove middle func # %d " 577844961713Sgirish "hw_p $%p parent dip $%p " 577944961713Sgirish "ndevs %d (middle)", 578044961713Sgirish nxgep->function_num, 578144961713Sgirish hw_p, 578244961713Sgirish p_dip, 578344961713Sgirish hw_p->ndevs)); 578444961713Sgirish h_hw_p->next = hw_p->next; 578544961713Sgirish } 578644961713Sgirish 578744961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 578844961713Sgirish } 578944961713Sgirish break; 579044961713Sgirish } else { 579144961713Sgirish h_hw_p = hw_p; 579244961713Sgirish } 579344961713Sgirish } 579444961713Sgirish 579544961713Sgirish MUTEX_EXIT(&nxge_common_lock); 579644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 579744961713Sgirish "==> nxge_uninit_common_device (nxge_hw_list) $%p", 579844961713Sgirish nxge_hw_list)); 579944961713Sgirish 580044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 580144961713Sgirish } 580259ac0c16Sdavemq 580359ac0c16Sdavemq /* 58042e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 580559ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 580659ac0c16Sdavemq */ 580759ac0c16Sdavemq 580859ac0c16Sdavemq int 58092e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 581059ac0c16Sdavemq { 581159ac0c16Sdavemq int nports = 0; 581259ac0c16Sdavemq 58132e59129aSraghus switch (nxgep->niu_type) { 581459ac0c16Sdavemq case N2_NIU: 581559ac0c16Sdavemq case NEPTUNE_2_10GF: 581659ac0c16Sdavemq nports = 2; 581759ac0c16Sdavemq break; 581859ac0c16Sdavemq case NEPTUNE_4_1GC: 581959ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 582059ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 582159ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 582259a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 582359ac0c16Sdavemq nports = 4; 582459ac0c16Sdavemq break; 582559ac0c16Sdavemq default: 58262e59129aSraghus switch (nxgep->platform_type) { 58272e59129aSraghus case P_NEPTUNE_NIU: 58282e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 58292e59129aSraghus nports = 2; 58302e59129aSraghus break; 58312e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 58322e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 58332e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 5834d81011f0Ssbehera case P_NEPTUNE_ALONSO: 58352e59129aSraghus nports = 4; 58362e59129aSraghus break; 58372e59129aSraghus default: 58382e59129aSraghus break; 58392e59129aSraghus } 584059ac0c16Sdavemq break; 584159ac0c16Sdavemq } 584259ac0c16Sdavemq 584359ac0c16Sdavemq return (nports); 584459ac0c16Sdavemq } 5845ec090658Sml 5846ec090658Sml /* 5847ec090658Sml * The following two functions are to support 5848ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 5849ec090658Sml */ 5850ec090658Sml static int 5851ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 5852ec090658Sml { 5853ec090658Sml int nmsi; 5854ec090658Sml extern int ncpus; 5855ec090658Sml 5856ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 5857ec090658Sml 5858ec090658Sml switch (nxgep->mac.portmode) { 5859ec090658Sml case PORT_10G_COPPER: 5860ec090658Sml case PORT_10G_FIBER: 5861ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 5862ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 5863ec090658Sml /* 5864ec090658Sml * The maximum MSI-X requested will be 8. 5865ec090658Sml * If the # of CPUs is less than 8, we will reqeust 5866ec090658Sml * # MSI-X based on the # of CPUs. 5867ec090658Sml */ 5868ec090658Sml if (ncpus >= NXGE_MSIX_REQUEST_10G) { 5869ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 5870ec090658Sml } else { 5871ec090658Sml nmsi = ncpus; 5872ec090658Sml } 5873ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 5874ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 5875ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 5876ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 5877ec090658Sml break; 5878ec090658Sml 5879ec090658Sml default: 5880ec090658Sml nmsi = NXGE_MSIX_REQUEST_1G; 5881ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 5882ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 5883ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 5884ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 5885ec090658Sml break; 5886ec090658Sml } 5887ec090658Sml 5888ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 5889ec090658Sml return (nmsi); 5890ec090658Sml } 5891