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); 20544961713Sgirish 20644961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 20744961713Sgirish #define MAX_DUMP_SZ 256 20844961713Sgirish 20944961713Sgirish #define NXGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB) 21044961713Sgirish 21144961713Sgirish static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 21244961713Sgirish static mac_callbacks_t nxge_m_callbacks = { 21344961713Sgirish NXGE_M_CALLBACK_FLAGS, 21444961713Sgirish nxge_m_stat, 21544961713Sgirish nxge_m_start, 21644961713Sgirish nxge_m_stop, 21744961713Sgirish nxge_m_promisc, 21844961713Sgirish nxge_m_multicst, 21944961713Sgirish nxge_m_unicst, 22044961713Sgirish nxge_m_tx, 22144961713Sgirish nxge_m_resources, 22244961713Sgirish nxge_m_ioctl, 22344961713Sgirish nxge_m_getcapab 22444961713Sgirish }; 22544961713Sgirish 22644961713Sgirish void 22744961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 22844961713Sgirish 229ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 230ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 231ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 232ec090658Sml static int nxge_create_msi_property(p_nxge_t); 233ec090658Sml 23444961713Sgirish /* 23544961713Sgirish * These global variables control the message 23644961713Sgirish * output. 23744961713Sgirish */ 23844961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 23944961713Sgirish uint64_t nxge_debug_level = 0; 24044961713Sgirish 24144961713Sgirish /* 24244961713Sgirish * This list contains the instance structures for the Neptune 24344961713Sgirish * devices present in the system. The lock exists to guarantee 24444961713Sgirish * mutually exclusive access to the list. 24544961713Sgirish */ 24644961713Sgirish void *nxge_list = NULL; 24744961713Sgirish 24844961713Sgirish void *nxge_hw_list = NULL; 24944961713Sgirish nxge_os_mutex_t nxge_common_lock; 25044961713Sgirish 25144961713Sgirish extern uint64_t npi_debug_level; 25244961713Sgirish 25344961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 25444961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 25544961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 25644961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 25744961713Sgirish extern void nxge_fm_init(p_nxge_t, 25844961713Sgirish ddi_device_acc_attr_t *, 25944961713Sgirish ddi_device_acc_attr_t *, 26044961713Sgirish ddi_dma_attr_t *); 26144961713Sgirish extern void nxge_fm_fini(p_nxge_t); 26258324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 26344961713Sgirish 26444961713Sgirish /* 26544961713Sgirish * Count used to maintain the number of buffers being used 26644961713Sgirish * by Neptune instances and loaned up to the upper layers. 26744961713Sgirish */ 26844961713Sgirish uint32_t nxge_mblks_pending = 0; 26944961713Sgirish 27044961713Sgirish /* 27144961713Sgirish * Device register access attributes for PIO. 27244961713Sgirish */ 27344961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 27444961713Sgirish DDI_DEVICE_ATTR_V0, 27544961713Sgirish DDI_STRUCTURE_LE_ACC, 27644961713Sgirish DDI_STRICTORDER_ACC, 27744961713Sgirish }; 27844961713Sgirish 27944961713Sgirish /* 28044961713Sgirish * Device descriptor access attributes for DMA. 28144961713Sgirish */ 28244961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 28344961713Sgirish DDI_DEVICE_ATTR_V0, 28444961713Sgirish DDI_STRUCTURE_LE_ACC, 28544961713Sgirish DDI_STRICTORDER_ACC 28644961713Sgirish }; 28744961713Sgirish 28844961713Sgirish /* 28944961713Sgirish * Device buffer access attributes for DMA. 29044961713Sgirish */ 29144961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 29244961713Sgirish DDI_DEVICE_ATTR_V0, 29344961713Sgirish DDI_STRUCTURE_BE_ACC, 29444961713Sgirish DDI_STRICTORDER_ACC 29544961713Sgirish }; 29644961713Sgirish 29744961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 29844961713Sgirish DMA_ATTR_V0, /* version number. */ 29944961713Sgirish 0, /* low address */ 30044961713Sgirish 0xffffffffffffffff, /* high address */ 30144961713Sgirish 0xffffffffffffffff, /* address counter max */ 30244961713Sgirish #ifndef NIU_PA_WORKAROUND 30344961713Sgirish 0x100000, /* alignment */ 30444961713Sgirish #else 30544961713Sgirish 0x2000, 30644961713Sgirish #endif 30744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 30844961713Sgirish 0x1, /* minimum transfer size */ 30944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 31044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 31144961713Sgirish 1, /* scatter/gather list length */ 31244961713Sgirish (unsigned int) 1, /* granularity */ 31344961713Sgirish 0 /* attribute flags */ 31444961713Sgirish }; 31544961713Sgirish 31644961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 31744961713Sgirish DMA_ATTR_V0, /* version number. */ 31844961713Sgirish 0, /* low address */ 31944961713Sgirish 0xffffffffffffffff, /* high address */ 32044961713Sgirish 0xffffffffffffffff, /* address counter max */ 32144961713Sgirish #if defined(_BIG_ENDIAN) 32244961713Sgirish 0x2000, /* alignment */ 32344961713Sgirish #else 32444961713Sgirish 0x1000, /* alignment */ 32544961713Sgirish #endif 32644961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 32744961713Sgirish 0x1, /* minimum transfer size */ 32844961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 32944961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 33044961713Sgirish 5, /* scatter/gather list length */ 33144961713Sgirish (unsigned int) 1, /* granularity */ 33244961713Sgirish 0 /* attribute flags */ 33344961713Sgirish }; 33444961713Sgirish 33544961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 33644961713Sgirish DMA_ATTR_V0, /* version number. */ 33744961713Sgirish 0, /* low address */ 33844961713Sgirish 0xffffffffffffffff, /* high address */ 33944961713Sgirish 0xffffffffffffffff, /* address counter max */ 34044961713Sgirish 0x2000, /* alignment */ 34144961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 34244961713Sgirish 0x1, /* minimum transfer size */ 34344961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 34444961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 34544961713Sgirish 1, /* scatter/gather list length */ 34644961713Sgirish (unsigned int) 1, /* granularity */ 3470e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 34844961713Sgirish }; 34944961713Sgirish 35044961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 35144961713Sgirish (uint_t)0, /* dlim_addr_lo */ 35244961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 35344961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 35444961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 35544961713Sgirish 0x1, /* dlim_minxfer */ 35644961713Sgirish 1024 /* dlim_speed */ 35744961713Sgirish }; 35844961713Sgirish 35944961713Sgirish dma_method_t nxge_force_dma = DVMA; 36044961713Sgirish 36144961713Sgirish /* 36244961713Sgirish * dma chunk sizes. 36344961713Sgirish * 36444961713Sgirish * Try to allocate the largest possible size 36544961713Sgirish * so that fewer number of dma chunks would be managed 36644961713Sgirish */ 36744961713Sgirish #ifdef NIU_PA_WORKAROUND 36844961713Sgirish size_t alloc_sizes [] = {0x2000}; 36944961713Sgirish #else 37044961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 37144961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 37230ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 37330ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 37444961713Sgirish #endif 37544961713Sgirish 37644961713Sgirish /* 37744961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 37844961713Sgirish */ 37944961713Sgirish 38044961713Sgirish static int 38144961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 38244961713Sgirish { 38344961713Sgirish p_nxge_t nxgep = NULL; 38444961713Sgirish int instance; 38544961713Sgirish int status = DDI_SUCCESS; 38644961713Sgirish uint8_t portn; 38758324dfcSspeer nxge_mmac_t *mmac_info; 38844961713Sgirish 38944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 39044961713Sgirish 39144961713Sgirish /* 39244961713Sgirish * Get the device instance since we'll need to setup 39344961713Sgirish * or retrieve a soft state for this instance. 39444961713Sgirish */ 39544961713Sgirish instance = ddi_get_instance(dip); 39644961713Sgirish 39744961713Sgirish switch (cmd) { 39844961713Sgirish case DDI_ATTACH: 39944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 40044961713Sgirish break; 40144961713Sgirish 40244961713Sgirish case DDI_RESUME: 40344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 40444961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 40544961713Sgirish if (nxgep == NULL) { 40644961713Sgirish status = DDI_FAILURE; 40744961713Sgirish break; 40844961713Sgirish } 40944961713Sgirish if (nxgep->dip != dip) { 41044961713Sgirish status = DDI_FAILURE; 41144961713Sgirish break; 41244961713Sgirish } 41344961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 41444961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 41544961713Sgirish } else { 41656d930aeSspeer status = nxge_resume(nxgep); 41744961713Sgirish } 41844961713Sgirish goto nxge_attach_exit; 41944961713Sgirish 42044961713Sgirish case DDI_PM_RESUME: 42144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 42244961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 42344961713Sgirish if (nxgep == NULL) { 42444961713Sgirish status = DDI_FAILURE; 42544961713Sgirish break; 42644961713Sgirish } 42744961713Sgirish if (nxgep->dip != dip) { 42844961713Sgirish status = DDI_FAILURE; 42944961713Sgirish break; 43044961713Sgirish } 43156d930aeSspeer status = nxge_resume(nxgep); 43244961713Sgirish goto nxge_attach_exit; 43344961713Sgirish 43444961713Sgirish default: 43544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 43644961713Sgirish status = DDI_FAILURE; 43744961713Sgirish goto nxge_attach_exit; 43844961713Sgirish } 43944961713Sgirish 44044961713Sgirish 44144961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 44244961713Sgirish status = DDI_FAILURE; 44344961713Sgirish goto nxge_attach_exit; 44444961713Sgirish } 44544961713Sgirish 44644961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 44744961713Sgirish if (nxgep == NULL) { 4482e59129aSraghus status = NXGE_ERROR; 4492e59129aSraghus goto nxge_attach_fail2; 45044961713Sgirish } 45144961713Sgirish 45298ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 45398ecde52Stm 45444961713Sgirish nxgep->drv_state = 0; 45544961713Sgirish nxgep->dip = dip; 45644961713Sgirish nxgep->instance = instance; 45744961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 45844961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 45944961713Sgirish npi_debug_level = nxge_debug_level; 46044961713Sgirish 46144961713Sgirish nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_dev_desc_dma_acc_attr, 46244961713Sgirish &nxge_rx_dma_attr); 46344961713Sgirish 46444961713Sgirish status = nxge_map_regs(nxgep); 46544961713Sgirish if (status != NXGE_OK) { 46644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 4672e59129aSraghus goto nxge_attach_fail3; 46844961713Sgirish } 46944961713Sgirish 47044961713Sgirish status = nxge_init_common_dev(nxgep); 47144961713Sgirish if (status != NXGE_OK) { 47244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 47344961713Sgirish "nxge_init_common_dev failed")); 4742e59129aSraghus goto nxge_attach_fail4; 47544961713Sgirish } 47644961713Sgirish 47759ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 47859ac0c16Sdavemq if (nxgep->function_num > 1) { 479*4202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 48059ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 48159ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 48259ac0c16Sdavemq status = NXGE_ERROR; 4832e59129aSraghus goto nxge_attach_fail4; 48459ac0c16Sdavemq } 48559ac0c16Sdavemq } 48659ac0c16Sdavemq 48744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 48844961713Sgirish nxgep->mac.portnum = portn; 48944961713Sgirish if ((portn == 0) || (portn == 1)) 49044961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 49144961713Sgirish else 49244961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 49358324dfcSspeer /* 49458324dfcSspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 49558324dfcSspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 49658324dfcSspeer * The two types of MACs have different characterizations. 49758324dfcSspeer */ 49858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 49958324dfcSspeer if (nxgep->function_num < 2) { 50058324dfcSspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 50158324dfcSspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 50258324dfcSspeer } else { 50358324dfcSspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 50458324dfcSspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 50558324dfcSspeer } 50644961713Sgirish /* 50744961713Sgirish * Setup the Ndd parameters for the this instance. 50844961713Sgirish */ 50944961713Sgirish nxge_init_param(nxgep); 51044961713Sgirish 51144961713Sgirish /* 51244961713Sgirish * Setup Register Tracing Buffer. 51344961713Sgirish */ 51444961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 51544961713Sgirish 51644961713Sgirish /* init stats ptr */ 51744961713Sgirish nxge_init_statsp(nxgep); 51856d930aeSspeer 5192e59129aSraghus /* 5202e59129aSraghus * read the vpd info from the eeprom into local data 5212e59129aSraghus * structure and check for the VPD info validity 5222e59129aSraghus */ 5232e59129aSraghus nxge_vpd_info_get(nxgep); 52456d930aeSspeer 5252e59129aSraghus status = nxge_xcvr_find(nxgep); 52644961713Sgirish 52744961713Sgirish if (status != NXGE_OK) { 52856d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 52944961713Sgirish " Couldn't determine card type" 53044961713Sgirish " .... exit ")); 5312e59129aSraghus goto nxge_attach_fail5; 53244961713Sgirish } 53344961713Sgirish 53444961713Sgirish status = nxge_get_config_properties(nxgep); 53544961713Sgirish 53644961713Sgirish if (status != NXGE_OK) { 53744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "get_hw create failed")); 53844961713Sgirish goto nxge_attach_fail; 53944961713Sgirish } 54044961713Sgirish 54144961713Sgirish /* 54244961713Sgirish * Setup the Kstats for the driver. 54344961713Sgirish */ 54444961713Sgirish nxge_setup_kstats(nxgep); 54544961713Sgirish 54644961713Sgirish nxge_setup_param(nxgep); 54744961713Sgirish 54844961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 54944961713Sgirish if (status != NXGE_OK) { 55044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 55144961713Sgirish goto nxge_attach_fail; 55244961713Sgirish } 55344961713Sgirish 55444961713Sgirish #if defined(sun4v) 55544961713Sgirish if (nxgep->niu_type == N2_NIU) { 55644961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 55744961713Sgirish bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 55844961713Sgirish if ((status = 55944961713Sgirish hsvc_register(&nxgep->niu_hsvc, 56044961713Sgirish &nxgep->niu_min_ver)) != 0) { 56144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 56244961713Sgirish "nxge_attach: " 56344961713Sgirish "%s: cannot negotiate " 56444961713Sgirish "hypervisor services " 56544961713Sgirish "revision %d " 56644961713Sgirish "group: 0x%lx " 56744961713Sgirish "major: 0x%lx minor: 0x%lx " 56844961713Sgirish "errno: %d", 56944961713Sgirish niu_hsvc.hsvc_modname, 57044961713Sgirish niu_hsvc.hsvc_rev, 57144961713Sgirish niu_hsvc.hsvc_group, 57244961713Sgirish niu_hsvc.hsvc_major, 57344961713Sgirish niu_hsvc.hsvc_minor, 57444961713Sgirish status)); 57544961713Sgirish status = DDI_FAILURE; 57644961713Sgirish goto nxge_attach_fail; 57744961713Sgirish } 57844961713Sgirish 57944961713Sgirish nxgep->niu_hsvc_available = B_TRUE; 58044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 58144961713Sgirish "NIU Hypervisor service enabled")); 58244961713Sgirish } 58344961713Sgirish #endif 58444961713Sgirish 58544961713Sgirish nxge_hw_id_init(nxgep); 58644961713Sgirish nxge_hw_init_niu_common(nxgep); 58744961713Sgirish 58844961713Sgirish status = nxge_setup_mutexes(nxgep); 58944961713Sgirish if (status != NXGE_OK) { 59044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 59144961713Sgirish goto nxge_attach_fail; 59244961713Sgirish } 59344961713Sgirish 59444961713Sgirish status = nxge_setup_dev(nxgep); 59544961713Sgirish if (status != DDI_SUCCESS) { 59644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 59744961713Sgirish goto nxge_attach_fail; 59844961713Sgirish } 59944961713Sgirish 60044961713Sgirish status = nxge_add_intrs(nxgep); 60144961713Sgirish if (status != DDI_SUCCESS) { 60244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 60344961713Sgirish goto nxge_attach_fail; 60444961713Sgirish } 60544961713Sgirish status = nxge_add_soft_intrs(nxgep); 60644961713Sgirish if (status != DDI_SUCCESS) { 60744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "add_soft_intr failed")); 60844961713Sgirish goto nxge_attach_fail; 60944961713Sgirish } 61044961713Sgirish 61144961713Sgirish /* 61244961713Sgirish * Enable interrupts. 61344961713Sgirish */ 61444961713Sgirish nxge_intrs_enable(nxgep); 61544961713Sgirish 6162e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 61744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 61844961713Sgirish "unable to register to mac layer (%d)", status)); 61944961713Sgirish goto nxge_attach_fail; 62044961713Sgirish } 62144961713Sgirish 62244961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 62344961713Sgirish 62444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "registered to mac (instance %d)", 62544961713Sgirish instance)); 62644961713Sgirish 62744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 62844961713Sgirish 62944961713Sgirish goto nxge_attach_exit; 63044961713Sgirish 63144961713Sgirish nxge_attach_fail: 63244961713Sgirish nxge_unattach(nxgep); 6332e59129aSraghus goto nxge_attach_fail1; 6342e59129aSraghus 6352e59129aSraghus nxge_attach_fail5: 6362e59129aSraghus /* 6372e59129aSraghus * Tear down the ndd parameters setup. 6382e59129aSraghus */ 6392e59129aSraghus nxge_destroy_param(nxgep); 6402e59129aSraghus 6412e59129aSraghus /* 6422e59129aSraghus * Tear down the kstat setup. 6432e59129aSraghus */ 6442e59129aSraghus nxge_destroy_kstats(nxgep); 6452e59129aSraghus 6462e59129aSraghus nxge_attach_fail4: 6472e59129aSraghus if (nxgep->nxge_hw_p) { 6482e59129aSraghus nxge_uninit_common_dev(nxgep); 6492e59129aSraghus nxgep->nxge_hw_p = NULL; 6502e59129aSraghus } 6512e59129aSraghus 6522e59129aSraghus nxge_attach_fail3: 6532e59129aSraghus /* 6542e59129aSraghus * Unmap the register setup. 6552e59129aSraghus */ 6562e59129aSraghus nxge_unmap_regs(nxgep); 6572e59129aSraghus 6582e59129aSraghus nxge_fm_fini(nxgep); 6592e59129aSraghus 6602e59129aSraghus nxge_attach_fail2: 6612e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 6622e59129aSraghus 6632e59129aSraghus nxge_attach_fail1: 66456d930aeSspeer if (status != NXGE_OK) 66556d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 66644961713Sgirish nxgep = NULL; 66744961713Sgirish 66844961713Sgirish nxge_attach_exit: 66944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 67044961713Sgirish status)); 67144961713Sgirish 67244961713Sgirish return (status); 67344961713Sgirish } 67444961713Sgirish 67544961713Sgirish static int 67644961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 67744961713Sgirish { 67844961713Sgirish int status = DDI_SUCCESS; 67944961713Sgirish int instance; 68044961713Sgirish p_nxge_t nxgep = NULL; 68144961713Sgirish 68244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 68344961713Sgirish instance = ddi_get_instance(dip); 68444961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 68544961713Sgirish if (nxgep == NULL) { 68644961713Sgirish status = DDI_FAILURE; 68744961713Sgirish goto nxge_detach_exit; 68844961713Sgirish } 68944961713Sgirish 69044961713Sgirish switch (cmd) { 69144961713Sgirish case DDI_DETACH: 69244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 69344961713Sgirish break; 69444961713Sgirish 69544961713Sgirish case DDI_PM_SUSPEND: 69644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 69744961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 69844961713Sgirish nxge_suspend(nxgep); 69944961713Sgirish break; 70044961713Sgirish 70144961713Sgirish case DDI_SUSPEND: 70244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 70344961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 70444961713Sgirish nxgep->suspended = DDI_SUSPEND; 70544961713Sgirish nxge_suspend(nxgep); 70644961713Sgirish } 70744961713Sgirish break; 70844961713Sgirish 70944961713Sgirish default: 71044961713Sgirish status = DDI_FAILURE; 71144961713Sgirish } 71244961713Sgirish 71344961713Sgirish if (cmd != DDI_DETACH) 71444961713Sgirish goto nxge_detach_exit; 71544961713Sgirish 71644961713Sgirish /* 71744961713Sgirish * Stop the xcvr polling. 71844961713Sgirish */ 71944961713Sgirish nxgep->suspended = cmd; 72044961713Sgirish 72144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 72244961713Sgirish 72344961713Sgirish if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 72444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 72544961713Sgirish "<== nxge_detach status = 0x%08X", status)); 72644961713Sgirish return (DDI_FAILURE); 72744961713Sgirish } 72844961713Sgirish 72944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 73044961713Sgirish "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 73144961713Sgirish 73244961713Sgirish nxge_unattach(nxgep); 73344961713Sgirish nxgep = NULL; 73444961713Sgirish 73544961713Sgirish nxge_detach_exit: 73644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 73744961713Sgirish status)); 73844961713Sgirish 73944961713Sgirish return (status); 74044961713Sgirish } 74144961713Sgirish 74244961713Sgirish static void 74344961713Sgirish nxge_unattach(p_nxge_t nxgep) 74444961713Sgirish { 74544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 74644961713Sgirish 74744961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 74844961713Sgirish return; 74944961713Sgirish } 75044961713Sgirish 75198ecde52Stm nxgep->nxge_magic = 0; 75298ecde52Stm 75344961713Sgirish if (nxgep->nxge_timerid) { 75444961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 75544961713Sgirish nxgep->nxge_timerid = 0; 75644961713Sgirish } 75744961713Sgirish 75853560810Ssbehera if (nxgep->nxge_hw_p) { 75953560810Ssbehera nxge_uninit_common_dev(nxgep); 76053560810Ssbehera nxgep->nxge_hw_p = NULL; 76153560810Ssbehera } 76253560810Ssbehera 76344961713Sgirish #if defined(sun4v) 76444961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 76544961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 76644961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 76744961713Sgirish } 76844961713Sgirish #endif 76944961713Sgirish /* 77044961713Sgirish * Stop any further interrupts. 77144961713Sgirish */ 77244961713Sgirish nxge_remove_intrs(nxgep); 77344961713Sgirish 77444961713Sgirish /* remove soft interrups */ 77544961713Sgirish nxge_remove_soft_intrs(nxgep); 77644961713Sgirish 77744961713Sgirish /* 77844961713Sgirish * Stop the device and free resources. 77944961713Sgirish */ 78044961713Sgirish nxge_destroy_dev(nxgep); 78144961713Sgirish 78244961713Sgirish /* 78344961713Sgirish * Tear down the ndd parameters setup. 78444961713Sgirish */ 78544961713Sgirish nxge_destroy_param(nxgep); 78644961713Sgirish 78744961713Sgirish /* 78844961713Sgirish * Tear down the kstat setup. 78944961713Sgirish */ 79044961713Sgirish nxge_destroy_kstats(nxgep); 79144961713Sgirish 79244961713Sgirish /* 79344961713Sgirish * Destroy all mutexes. 79444961713Sgirish */ 79544961713Sgirish nxge_destroy_mutexes(nxgep); 79644961713Sgirish 79744961713Sgirish /* 79844961713Sgirish * Remove the list of ndd parameters which 79944961713Sgirish * were setup during attach. 80044961713Sgirish */ 80144961713Sgirish if (nxgep->dip) { 80244961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 80344961713Sgirish " nxge_unattach: remove all properties")); 80444961713Sgirish 80544961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 80644961713Sgirish } 80744961713Sgirish 80844961713Sgirish #if NXGE_PROPERTY 80944961713Sgirish nxge_remove_hard_properties(nxgep); 81044961713Sgirish #endif 81144961713Sgirish 81244961713Sgirish /* 81344961713Sgirish * Unmap the register setup. 81444961713Sgirish */ 81544961713Sgirish nxge_unmap_regs(nxgep); 81644961713Sgirish 81744961713Sgirish nxge_fm_fini(nxgep); 81844961713Sgirish 81944961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 82044961713Sgirish 82144961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 82244961713Sgirish } 82344961713Sgirish 82444961713Sgirish static char n2_siu_name[] = "niu"; 82544961713Sgirish 82644961713Sgirish static nxge_status_t 82744961713Sgirish nxge_map_regs(p_nxge_t nxgep) 82844961713Sgirish { 82944961713Sgirish int ddi_status = DDI_SUCCESS; 83044961713Sgirish p_dev_regs_t dev_regs; 83144961713Sgirish char buf[MAXPATHLEN + 1]; 83244961713Sgirish char *devname; 83344961713Sgirish #ifdef NXGE_DEBUG 83444961713Sgirish char *sysname; 83544961713Sgirish #endif 83644961713Sgirish off_t regsize; 83744961713Sgirish nxge_status_t status = NXGE_OK; 83814ea4bb7Ssd #if !defined(_BIG_ENDIAN) 83914ea4bb7Ssd off_t pci_offset; 84014ea4bb7Ssd uint16_t pcie_devctl; 84114ea4bb7Ssd #endif 84244961713Sgirish 84344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 84444961713Sgirish nxgep->dev_regs = NULL; 84544961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 84644961713Sgirish dev_regs->nxge_regh = NULL; 84744961713Sgirish dev_regs->nxge_pciregh = NULL; 84844961713Sgirish dev_regs->nxge_msix_regh = NULL; 84944961713Sgirish dev_regs->nxge_vir_regh = NULL; 85044961713Sgirish dev_regs->nxge_vir2_regh = NULL; 85159ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 85244961713Sgirish 85344961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 85444961713Sgirish ASSERT(strlen(devname) > 0); 85544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 85644961713Sgirish "nxge_map_regs: pathname devname %s", devname)); 85744961713Sgirish 85844961713Sgirish if (strstr(devname, n2_siu_name)) { 85944961713Sgirish /* N2/NIU */ 86044961713Sgirish nxgep->niu_type = N2_NIU; 86144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 86244961713Sgirish "nxge_map_regs: N2/NIU devname %s", devname)); 86344961713Sgirish /* get function number */ 86444961713Sgirish nxgep->function_num = 86544961713Sgirish (devname[strlen(devname) -1] == '1' ? 1 : 0); 86644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 86744961713Sgirish "nxge_map_regs: N2/NIU function number %d", 86844961713Sgirish nxgep->function_num)); 86944961713Sgirish } else { 87044961713Sgirish int *prop_val; 87144961713Sgirish uint_t prop_len; 87244961713Sgirish uint8_t func_num; 87344961713Sgirish 87444961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 87544961713Sgirish 0, "reg", 87644961713Sgirish &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 87744961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 87844961713Sgirish "Reg property not found")); 87944961713Sgirish ddi_status = DDI_FAILURE; 88044961713Sgirish goto nxge_map_regs_fail0; 88144961713Sgirish 88244961713Sgirish } else { 88344961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 88444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 88544961713Sgirish "Reg property found: fun # %d", 88644961713Sgirish func_num)); 88744961713Sgirish nxgep->function_num = func_num; 88844961713Sgirish ddi_prop_free(prop_val); 88944961713Sgirish } 89044961713Sgirish } 89144961713Sgirish 89244961713Sgirish switch (nxgep->niu_type) { 89344961713Sgirish default: 89444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 89544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 89644961713Sgirish "nxge_map_regs: pci config size 0x%x", regsize)); 89744961713Sgirish 89844961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 89944961713Sgirish (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 90044961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 90144961713Sgirish if (ddi_status != DDI_SUCCESS) { 90244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 90344961713Sgirish "ddi_map_regs, nxge bus config regs failed")); 90444961713Sgirish goto nxge_map_regs_fail0; 90544961713Sgirish } 90644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 90744961713Sgirish "nxge_map_reg: PCI config addr 0x%0llx " 90844961713Sgirish " handle 0x%0llx", dev_regs->nxge_pciregp, 90944961713Sgirish dev_regs->nxge_pciregh)); 91044961713Sgirish /* 91144961713Sgirish * IMP IMP 91244961713Sgirish * workaround for bit swapping bug in HW 91344961713Sgirish * which ends up in no-snoop = yes 91444961713Sgirish * resulting, in DMA not synched properly 91544961713Sgirish */ 91644961713Sgirish #if !defined(_BIG_ENDIAN) 91714ea4bb7Ssd /* workarounds for x86 systems */ 91814ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 91914ea4bb7Ssd pcie_devctl = 0x0; 92014ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 92114ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 92214ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 92314ea4bb7Ssd pcie_devctl); 92444961713Sgirish #endif 92514ea4bb7Ssd 92644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 92744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 92844961713Sgirish "nxge_map_regs: pio size 0x%x", regsize)); 92944961713Sgirish /* set up the device mapped register */ 93044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 93144961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 93244961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 93344961713Sgirish if (ddi_status != DDI_SUCCESS) { 93444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 93544961713Sgirish "ddi_map_regs for Neptune global reg failed")); 93644961713Sgirish goto nxge_map_regs_fail1; 93744961713Sgirish } 93844961713Sgirish 93944961713Sgirish /* set up the msi/msi-x mapped register */ 94044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 94144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 94244961713Sgirish "nxge_map_regs: msix size 0x%x", regsize)); 94344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 94444961713Sgirish (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 94544961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 94644961713Sgirish if (ddi_status != DDI_SUCCESS) { 94744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 94844961713Sgirish "ddi_map_regs for msi reg failed")); 94944961713Sgirish goto nxge_map_regs_fail2; 95044961713Sgirish } 95144961713Sgirish 95244961713Sgirish /* set up the vio region mapped register */ 95344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 95444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 95544961713Sgirish "nxge_map_regs: vio size 0x%x", regsize)); 95644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 95744961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 95844961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 95944961713Sgirish 96044961713Sgirish if (ddi_status != DDI_SUCCESS) { 96144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 96244961713Sgirish "ddi_map_regs for nxge vio reg failed")); 96344961713Sgirish goto nxge_map_regs_fail3; 96444961713Sgirish } 96544961713Sgirish nxgep->dev_regs = dev_regs; 96644961713Sgirish 96744961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 96844961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 96944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_pciregp); 97044961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 97144961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 97244961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 97344961713Sgirish 97444961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 97544961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 97644961713Sgirish 97744961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 97844961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 97944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 98044961713Sgirish 98144961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 98244961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 98344961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 98444961713Sgirish 98544961713Sgirish break; 98644961713Sgirish 98744961713Sgirish case N2_NIU: 98844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 98944961713Sgirish /* 99044961713Sgirish * Set up the device mapped register (FWARC 2006/556) 99144961713Sgirish * (changed back to 1: reg starts at 1!) 99244961713Sgirish */ 99344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 99444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 99544961713Sgirish "nxge_map_regs: dev size 0x%x", regsize)); 99644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 99744961713Sgirish (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 99844961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 99944961713Sgirish 100044961713Sgirish if (ddi_status != DDI_SUCCESS) { 100144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 100244961713Sgirish "ddi_map_regs for N2/NIU, global reg failed ")); 100344961713Sgirish goto nxge_map_regs_fail1; 100444961713Sgirish } 100544961713Sgirish 100644961713Sgirish /* set up the vio region mapped register */ 100744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 100844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 100944961713Sgirish "nxge_map_regs: vio (1) size 0x%x", regsize)); 101044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 101144961713Sgirish (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 101244961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 101344961713Sgirish 101444961713Sgirish if (ddi_status != DDI_SUCCESS) { 101544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 101644961713Sgirish "ddi_map_regs for nxge vio reg failed")); 101744961713Sgirish goto nxge_map_regs_fail2; 101844961713Sgirish } 101944961713Sgirish /* set up the vio region mapped register */ 102044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 102144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 102244961713Sgirish "nxge_map_regs: vio (3) size 0x%x", regsize)); 102344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 102444961713Sgirish (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 102544961713Sgirish &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 102644961713Sgirish 102744961713Sgirish if (ddi_status != DDI_SUCCESS) { 102844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 102944961713Sgirish "ddi_map_regs for nxge vio2 reg failed")); 103044961713Sgirish goto nxge_map_regs_fail3; 103144961713Sgirish } 103244961713Sgirish nxgep->dev_regs = dev_regs; 103344961713Sgirish 103444961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 103544961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 103644961713Sgirish 103744961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 103844961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 103944961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_regp); 104044961713Sgirish 104144961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 104244961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 104344961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 104444961713Sgirish 104544961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 104644961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 104744961713Sgirish (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 104844961713Sgirish 104944961713Sgirish break; 105044961713Sgirish } 105144961713Sgirish 105244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 105344961713Sgirish " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 105444961713Sgirish 105544961713Sgirish goto nxge_map_regs_exit; 105644961713Sgirish nxge_map_regs_fail3: 105744961713Sgirish if (dev_regs->nxge_msix_regh) { 105844961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 105944961713Sgirish } 106044961713Sgirish if (dev_regs->nxge_vir_regh) { 106144961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 106244961713Sgirish } 106344961713Sgirish nxge_map_regs_fail2: 106444961713Sgirish if (dev_regs->nxge_regh) { 106544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 106644961713Sgirish } 106744961713Sgirish nxge_map_regs_fail1: 106844961713Sgirish if (dev_regs->nxge_pciregh) { 106944961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 107044961713Sgirish } 107144961713Sgirish nxge_map_regs_fail0: 107244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 107344961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 107444961713Sgirish 107544961713Sgirish nxge_map_regs_exit: 107644961713Sgirish if (ddi_status != DDI_SUCCESS) 107744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 107844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 107944961713Sgirish return (status); 108044961713Sgirish } 108144961713Sgirish 108244961713Sgirish static void 108344961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 108444961713Sgirish { 108544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 108644961713Sgirish if (nxgep->dev_regs) { 108744961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 108844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 108944961713Sgirish "==> nxge_unmap_regs: bus")); 109044961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 109144961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 109244961713Sgirish } 109344961713Sgirish if (nxgep->dev_regs->nxge_regh) { 109444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 109544961713Sgirish "==> nxge_unmap_regs: device registers")); 109644961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 109744961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 109844961713Sgirish } 109944961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 110044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 110144961713Sgirish "==> nxge_unmap_regs: device interrupts")); 110244961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 110344961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 110444961713Sgirish } 110544961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 110644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 110744961713Sgirish "==> nxge_unmap_regs: vio region")); 110844961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 110944961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 111044961713Sgirish } 111144961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 111244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 111344961713Sgirish "==> nxge_unmap_regs: vio2 region")); 111444961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 111544961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 111644961713Sgirish } 111744961713Sgirish 111844961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 111944961713Sgirish nxgep->dev_regs = NULL; 112044961713Sgirish } 112144961713Sgirish 112244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 112344961713Sgirish } 112444961713Sgirish 112544961713Sgirish static nxge_status_t 112644961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 112744961713Sgirish { 112844961713Sgirish int ddi_status = DDI_SUCCESS; 112944961713Sgirish nxge_status_t status = NXGE_OK; 113044961713Sgirish nxge_classify_t *classify_ptr; 113144961713Sgirish int partition; 113244961713Sgirish 113344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 113444961713Sgirish 113544961713Sgirish /* 113644961713Sgirish * Get the interrupt cookie so the mutexes can be 113758324dfcSspeer * Initialized. 113844961713Sgirish */ 113944961713Sgirish ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 114044961713Sgirish &nxgep->interrupt_cookie); 114144961713Sgirish if (ddi_status != DDI_SUCCESS) { 114244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 114344961713Sgirish "<== nxge_setup_mutexes: failed 0x%x", ddi_status)); 114444961713Sgirish goto nxge_setup_mutexes_exit; 114544961713Sgirish } 114644961713Sgirish 114798ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 114898ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 114998ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 115098ecde52Stm 115144961713Sgirish /* 115298ecde52Stm * Initialize mutexes for this device. 115344961713Sgirish */ 115444961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 115544961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 115644961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 115744961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 115844961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 115944961713Sgirish MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 116044961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 116144961713Sgirish RW_DRIVER, (void *)nxgep->interrupt_cookie); 116244961713Sgirish 116344961713Sgirish classify_ptr = &nxgep->classifier; 116444961713Sgirish /* 116544961713Sgirish * FFLP Mutexes are never used in interrupt context 116644961713Sgirish * as fflp operation can take very long time to 116744961713Sgirish * complete and hence not suitable to invoke from interrupt 116844961713Sgirish * handlers. 116944961713Sgirish */ 117044961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 117159ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 11722e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 117344961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 117459ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 117544961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 117644961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 117744961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 117844961713Sgirish } 117944961713Sgirish } 118044961713Sgirish 118144961713Sgirish nxge_setup_mutexes_exit: 118244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 118359ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 118444961713Sgirish 118544961713Sgirish if (ddi_status != DDI_SUCCESS) 118644961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 118744961713Sgirish 118844961713Sgirish return (status); 118944961713Sgirish } 119044961713Sgirish 119144961713Sgirish static void 119244961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 119344961713Sgirish { 119444961713Sgirish int partition; 119544961713Sgirish nxge_classify_t *classify_ptr; 119644961713Sgirish 119744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 119844961713Sgirish RW_DESTROY(&nxgep->filter_lock); 119944961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 120044961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 120144961713Sgirish MUTEX_DESTROY(nxgep->genlock); 120244961713Sgirish 120344961713Sgirish classify_ptr = &nxgep->classifier; 120444961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 120544961713Sgirish 120698ecde52Stm /* Destroy all polling resources. */ 120798ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 120898ecde52Stm cv_destroy(&nxgep->poll_cv); 120998ecde52Stm 121098ecde52Stm /* free data structures, based on HW type */ 12112e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 121244961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 121344961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 121444961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 121544961713Sgirish } 121644961713Sgirish } 121744961713Sgirish 121844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 121944961713Sgirish } 122044961713Sgirish 122144961713Sgirish nxge_status_t 122244961713Sgirish nxge_init(p_nxge_t nxgep) 122344961713Sgirish { 122444961713Sgirish nxge_status_t status = NXGE_OK; 122544961713Sgirish 122644961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 122744961713Sgirish 122814ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 122914ea4bb7Ssd return (status); 123014ea4bb7Ssd } 123114ea4bb7Ssd 123244961713Sgirish /* 123344961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 123444961713Sgirish * and receive/transmit descriptor rings. 123544961713Sgirish */ 123644961713Sgirish status = nxge_alloc_mem_pool(nxgep); 123744961713Sgirish if (status != NXGE_OK) { 123844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 123944961713Sgirish goto nxge_init_fail1; 124044961713Sgirish } 124144961713Sgirish 124244961713Sgirish /* 124344961713Sgirish * Initialize and enable TXC registers 124444961713Sgirish * (Globally enable TX controller, 124544961713Sgirish * enable a port, configure dma channel bitmap, 124644961713Sgirish * configure the max burst size). 124744961713Sgirish */ 124844961713Sgirish status = nxge_txc_init(nxgep); 124944961713Sgirish if (status != NXGE_OK) { 125044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txc failed\n")); 125144961713Sgirish goto nxge_init_fail2; 125244961713Sgirish } 125344961713Sgirish 125444961713Sgirish /* 125544961713Sgirish * Initialize and enable TXDMA channels. 125644961713Sgirish */ 125744961713Sgirish status = nxge_init_txdma_channels(nxgep); 125844961713Sgirish if (status != NXGE_OK) { 125944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 126044961713Sgirish goto nxge_init_fail3; 126144961713Sgirish } 126244961713Sgirish 126344961713Sgirish /* 126444961713Sgirish * Initialize and enable RXDMA channels. 126544961713Sgirish */ 126644961713Sgirish status = nxge_init_rxdma_channels(nxgep); 126744961713Sgirish if (status != NXGE_OK) { 126844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 126944961713Sgirish goto nxge_init_fail4; 127044961713Sgirish } 127144961713Sgirish 127244961713Sgirish /* 127344961713Sgirish * Initialize TCAM and FCRAM (Neptune). 127444961713Sgirish */ 127544961713Sgirish status = nxge_classify_init(nxgep); 127644961713Sgirish if (status != NXGE_OK) { 127744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 127844961713Sgirish goto nxge_init_fail5; 127944961713Sgirish } 128044961713Sgirish 128144961713Sgirish /* 128244961713Sgirish * Initialize ZCP 128344961713Sgirish */ 128444961713Sgirish status = nxge_zcp_init(nxgep); 128544961713Sgirish if (status != NXGE_OK) { 128644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 128744961713Sgirish goto nxge_init_fail5; 128844961713Sgirish } 128944961713Sgirish 129044961713Sgirish /* 129144961713Sgirish * Initialize IPP. 129244961713Sgirish */ 129344961713Sgirish status = nxge_ipp_init(nxgep); 129444961713Sgirish if (status != NXGE_OK) { 129544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 129644961713Sgirish goto nxge_init_fail5; 129744961713Sgirish } 129844961713Sgirish 129944961713Sgirish /* 130044961713Sgirish * Initialize the MAC block. 130144961713Sgirish */ 130244961713Sgirish status = nxge_mac_init(nxgep); 130344961713Sgirish if (status != NXGE_OK) { 130444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 130544961713Sgirish goto nxge_init_fail5; 130644961713Sgirish } 130744961713Sgirish 130844961713Sgirish nxge_intrs_enable(nxgep); 130944961713Sgirish 131044961713Sgirish /* 131144961713Sgirish * Enable hardware interrupts. 131244961713Sgirish */ 131344961713Sgirish nxge_intr_hw_enable(nxgep); 131444961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 131544961713Sgirish 131644961713Sgirish goto nxge_init_exit; 131744961713Sgirish 131844961713Sgirish nxge_init_fail5: 131944961713Sgirish nxge_uninit_rxdma_channels(nxgep); 132044961713Sgirish nxge_init_fail4: 132144961713Sgirish nxge_uninit_txdma_channels(nxgep); 132244961713Sgirish nxge_init_fail3: 132344961713Sgirish (void) nxge_txc_uninit(nxgep); 132444961713Sgirish nxge_init_fail2: 132544961713Sgirish nxge_free_mem_pool(nxgep); 132644961713Sgirish nxge_init_fail1: 132744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 132844961713Sgirish "<== nxge_init status (failed) = 0x%08x", status)); 132944961713Sgirish return (status); 133044961713Sgirish 133144961713Sgirish nxge_init_exit: 133244961713Sgirish 133344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 133444961713Sgirish status)); 133544961713Sgirish return (status); 133644961713Sgirish } 133744961713Sgirish 133844961713Sgirish 133944961713Sgirish timeout_id_t 134044961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 134144961713Sgirish { 134244961713Sgirish if ((nxgep->suspended == 0) || 134344961713Sgirish (nxgep->suspended == DDI_RESUME)) { 134444961713Sgirish return (timeout(func, (caddr_t)nxgep, 134544961713Sgirish drv_usectohz(1000 * msec))); 134644961713Sgirish } 134744961713Sgirish return (NULL); 134844961713Sgirish } 134944961713Sgirish 135044961713Sgirish /*ARGSUSED*/ 135144961713Sgirish void 135244961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 135344961713Sgirish { 135444961713Sgirish if (timerid) { 135544961713Sgirish (void) untimeout(timerid); 135644961713Sgirish } 135744961713Sgirish } 135844961713Sgirish 135944961713Sgirish void 136044961713Sgirish nxge_uninit(p_nxge_t nxgep) 136144961713Sgirish { 136244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 136344961713Sgirish 136444961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 136544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 136644961713Sgirish "==> nxge_uninit: not initialized")); 136744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 136844961713Sgirish "<== nxge_uninit")); 136944961713Sgirish return; 137044961713Sgirish } 137144961713Sgirish 137244961713Sgirish /* stop timer */ 137344961713Sgirish if (nxgep->nxge_timerid) { 137444961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 137544961713Sgirish nxgep->nxge_timerid = 0; 137644961713Sgirish } 137744961713Sgirish 137844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 137944961713Sgirish (void) nxge_intr_hw_disable(nxgep); 138044961713Sgirish 138144961713Sgirish /* 138244961713Sgirish * Reset the receive MAC side. 138344961713Sgirish */ 138444961713Sgirish (void) nxge_rx_mac_disable(nxgep); 138544961713Sgirish 138644961713Sgirish /* Disable and soft reset the IPP */ 138744961713Sgirish (void) nxge_ipp_disable(nxgep); 138844961713Sgirish 1389a3c5bd6dSspeer /* Free classification resources */ 1390a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1391a3c5bd6dSspeer 139244961713Sgirish /* 139344961713Sgirish * Reset the transmit/receive DMA side. 139444961713Sgirish */ 139544961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 139644961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 139744961713Sgirish 139844961713Sgirish nxge_uninit_txdma_channels(nxgep); 139944961713Sgirish nxge_uninit_rxdma_channels(nxgep); 140044961713Sgirish 140144961713Sgirish /* 140244961713Sgirish * Reset the transmit MAC side. 140344961713Sgirish */ 140444961713Sgirish (void) nxge_tx_mac_disable(nxgep); 140544961713Sgirish 140644961713Sgirish nxge_free_mem_pool(nxgep); 140744961713Sgirish 140844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 140944961713Sgirish 141044961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 141144961713Sgirish 141244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 141344961713Sgirish "nxge_mblks_pending %d", nxge_mblks_pending)); 141444961713Sgirish } 141544961713Sgirish 141644961713Sgirish void 141744961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 141844961713Sgirish { 1419adfcba55Sjoycey #if defined(__i386) 1420adfcba55Sjoycey size_t reg; 1421adfcba55Sjoycey #else 142244961713Sgirish uint64_t reg; 1423adfcba55Sjoycey #endif 142444961713Sgirish uint64_t regdata; 142544961713Sgirish int i, retry; 142644961713Sgirish 142744961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 142844961713Sgirish regdata = 0; 142944961713Sgirish retry = 1; 143044961713Sgirish 143144961713Sgirish for (i = 0; i < retry; i++) { 143244961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 143344961713Sgirish } 143444961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 143544961713Sgirish } 143644961713Sgirish 143744961713Sgirish void 143844961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 143944961713Sgirish { 1440adfcba55Sjoycey #if defined(__i386) 1441adfcba55Sjoycey size_t reg; 1442adfcba55Sjoycey #else 144344961713Sgirish uint64_t reg; 1444adfcba55Sjoycey #endif 144544961713Sgirish uint64_t buf[2]; 144644961713Sgirish 144744961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 14487a8b1321Sjoycey #if defined(__i386) 14497a8b1321Sjoycey reg = (size_t)buf[0]; 14507a8b1321Sjoycey #else 145144961713Sgirish reg = buf[0]; 14527a8b1321Sjoycey #endif 145344961713Sgirish 145444961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 145544961713Sgirish } 145644961713Sgirish 145744961713Sgirish 145844961713Sgirish nxge_os_mutex_t nxgedebuglock; 145944961713Sgirish int nxge_debug_init = 0; 146044961713Sgirish 146144961713Sgirish /*ARGSUSED*/ 146244961713Sgirish /*VARARGS*/ 146344961713Sgirish void 146444961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 146544961713Sgirish { 146644961713Sgirish char msg_buffer[1048]; 146744961713Sgirish char prefix_buffer[32]; 146844961713Sgirish int instance; 146944961713Sgirish uint64_t debug_level; 147044961713Sgirish int cmn_level = CE_CONT; 147144961713Sgirish va_list ap; 147244961713Sgirish 147344961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 147444961713Sgirish nxgep->nxge_debug_level; 147544961713Sgirish 147644961713Sgirish if ((level & debug_level) || 147744961713Sgirish (level == NXGE_NOTE) || 147844961713Sgirish (level == NXGE_ERR_CTL)) { 147944961713Sgirish /* do the msg processing */ 148044961713Sgirish if (nxge_debug_init == 0) { 148144961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 148244961713Sgirish nxge_debug_init = 1; 148344961713Sgirish } 148444961713Sgirish 148544961713Sgirish MUTEX_ENTER(&nxgedebuglock); 148644961713Sgirish 148744961713Sgirish if ((level & NXGE_NOTE)) { 148844961713Sgirish cmn_level = CE_NOTE; 148944961713Sgirish } 149044961713Sgirish 149144961713Sgirish if (level & NXGE_ERR_CTL) { 149244961713Sgirish cmn_level = CE_WARN; 149344961713Sgirish } 149444961713Sgirish 149544961713Sgirish va_start(ap, fmt); 149644961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 149744961713Sgirish va_end(ap); 149844961713Sgirish if (nxgep == NULL) { 149944961713Sgirish instance = -1; 150044961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 150144961713Sgirish } else { 150244961713Sgirish instance = nxgep->instance; 150344961713Sgirish (void) sprintf(prefix_buffer, 150444961713Sgirish "%s%d :", "nxge", instance); 150544961713Sgirish } 150644961713Sgirish 150744961713Sgirish MUTEX_EXIT(&nxgedebuglock); 150844961713Sgirish cmn_err(cmn_level, "!%s %s\n", 150944961713Sgirish prefix_buffer, msg_buffer); 151044961713Sgirish 151144961713Sgirish } 151244961713Sgirish } 151344961713Sgirish 151444961713Sgirish char * 151544961713Sgirish nxge_dump_packet(char *addr, int size) 151644961713Sgirish { 151744961713Sgirish uchar_t *ap = (uchar_t *)addr; 151844961713Sgirish int i; 151944961713Sgirish static char etherbuf[1024]; 152044961713Sgirish char *cp = etherbuf; 152144961713Sgirish char digits[] = "0123456789abcdef"; 152244961713Sgirish 152344961713Sgirish if (!size) 152444961713Sgirish size = 60; 152544961713Sgirish 152644961713Sgirish if (size > MAX_DUMP_SZ) { 152744961713Sgirish /* Dump the leading bytes */ 152844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 152944961713Sgirish if (*ap > 0x0f) 153044961713Sgirish *cp++ = digits[*ap >> 4]; 153144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 153244961713Sgirish *cp++ = ':'; 153344961713Sgirish } 153444961713Sgirish for (i = 0; i < 20; i++) 153544961713Sgirish *cp++ = '.'; 153644961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 153744961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 153844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 153944961713Sgirish if (*ap > 0x0f) 154044961713Sgirish *cp++ = digits[*ap >> 4]; 154144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 154244961713Sgirish *cp++ = ':'; 154344961713Sgirish } 154444961713Sgirish } else { 154544961713Sgirish for (i = 0; i < size; i++) { 154644961713Sgirish if (*ap > 0x0f) 154744961713Sgirish *cp++ = digits[*ap >> 4]; 154844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 154944961713Sgirish *cp++ = ':'; 155044961713Sgirish } 155144961713Sgirish } 155244961713Sgirish *--cp = 0; 155344961713Sgirish return (etherbuf); 155444961713Sgirish } 155544961713Sgirish 155644961713Sgirish #ifdef NXGE_DEBUG 155744961713Sgirish static void 155844961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 155944961713Sgirish { 156044961713Sgirish ddi_acc_handle_t cfg_handle; 156144961713Sgirish p_pci_cfg_t cfg_ptr; 156244961713Sgirish ddi_acc_handle_t dev_handle; 156344961713Sgirish char *dev_ptr; 156444961713Sgirish ddi_acc_handle_t pci_config_handle; 156544961713Sgirish uint32_t regval; 156644961713Sgirish int i; 156744961713Sgirish 156844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 156944961713Sgirish 157044961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 157144961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 157244961713Sgirish 15732e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 157444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 157544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 157644961713Sgirish 157744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 157859ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 157944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 158059ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 158159ac0c16Sdavemq &cfg_ptr->vendorid)); 158244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 158359ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 158459ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 158559ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 158644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 158759ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 158859ac0c16Sdavemq "bar1c 0x%x", 158959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 159059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 159159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 159259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 159344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 159459ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 159559ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 159659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 159759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 159859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 159959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 160044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 160159ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 160259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 160344961713Sgirish 160444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 160544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 160644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 160759ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 160859ac0c16Sdavemq "last 0x%llx ", 160959ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 161059ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 161159ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 161259ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 161359ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 161459ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 161559ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 161659ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 161744961713Sgirish } 161844961713Sgirish } 161944961713Sgirish 162044961713Sgirish #endif 162144961713Sgirish 162244961713Sgirish static void 162344961713Sgirish nxge_suspend(p_nxge_t nxgep) 162444961713Sgirish { 162544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 162644961713Sgirish 162744961713Sgirish nxge_intrs_disable(nxgep); 162844961713Sgirish nxge_destroy_dev(nxgep); 162944961713Sgirish 163044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 163144961713Sgirish } 163244961713Sgirish 163344961713Sgirish static nxge_status_t 163444961713Sgirish nxge_resume(p_nxge_t nxgep) 163544961713Sgirish { 163644961713Sgirish nxge_status_t status = NXGE_OK; 163744961713Sgirish 163844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 163944961713Sgirish 164091c98b31Sjoycey nxgep->suspended = DDI_RESUME; 164191c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 164291c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 164391c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 164491c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 164591c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 164691c98b31Sjoycey nxge_intrs_enable(nxgep); 164744961713Sgirish nxgep->suspended = 0; 164844961713Sgirish 164944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 165044961713Sgirish "<== nxge_resume status = 0x%x", status)); 165144961713Sgirish return (status); 165244961713Sgirish } 165344961713Sgirish 165444961713Sgirish static nxge_status_t 165544961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 165644961713Sgirish { 165744961713Sgirish nxge_status_t status = NXGE_OK; 165844961713Sgirish 165944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 166059ac0c16Sdavemq nxgep->mac.portnum)); 166144961713Sgirish 166244961713Sgirish status = nxge_link_init(nxgep); 166314ea4bb7Ssd 166414ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 166514ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 166614ea4bb7Ssd "port%d Bad register acc handle", nxgep->mac.portnum)); 166714ea4bb7Ssd status = NXGE_ERROR; 166814ea4bb7Ssd } 166914ea4bb7Ssd 167044961713Sgirish if (status != NXGE_OK) { 167144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 167244961713Sgirish " nxge_setup_dev status " 167344961713Sgirish "(xcvr init 0x%08x)", status)); 167444961713Sgirish goto nxge_setup_dev_exit; 167544961713Sgirish } 167644961713Sgirish 167744961713Sgirish nxge_setup_dev_exit: 167844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 167944961713Sgirish "<== nxge_setup_dev port %d status = 0x%08x", 168044961713Sgirish nxgep->mac.portnum, status)); 168144961713Sgirish 168244961713Sgirish return (status); 168344961713Sgirish } 168444961713Sgirish 168544961713Sgirish static void 168644961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 168744961713Sgirish { 168844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 168944961713Sgirish 169044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 169144961713Sgirish 169244961713Sgirish (void) nxge_hw_stop(nxgep); 169344961713Sgirish 169444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 169544961713Sgirish } 169644961713Sgirish 169744961713Sgirish static nxge_status_t 169844961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 169944961713Sgirish { 170044961713Sgirish int ddi_status = DDI_SUCCESS; 170144961713Sgirish uint_t count; 170244961713Sgirish ddi_dma_cookie_t cookie; 170344961713Sgirish uint_t iommu_pagesize; 170444961713Sgirish nxge_status_t status = NXGE_OK; 170544961713Sgirish 170644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 170744961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 170844961713Sgirish if (nxgep->niu_type != N2_NIU) { 170944961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 171044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 171144961713Sgirish " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 171244961713Sgirish " default_block_size %d iommu_pagesize %d", 171344961713Sgirish nxgep->sys_page_sz, 171444961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 171544961713Sgirish nxgep->rx_default_block_size, 171644961713Sgirish iommu_pagesize)); 171744961713Sgirish 171844961713Sgirish if (iommu_pagesize != 0) { 171944961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 172044961713Sgirish if (iommu_pagesize > 0x4000) 172144961713Sgirish nxgep->sys_page_sz = 0x4000; 172244961713Sgirish } else { 172344961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 172444961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 172544961713Sgirish } 172644961713Sgirish } 172744961713Sgirish } 172844961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 172944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 173044961713Sgirish "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 173144961713Sgirish "default_block_size %d page mask %d", 173244961713Sgirish nxgep->sys_page_sz, 173344961713Sgirish ddi_ptob(nxgep->dip, (ulong_t)1), 173444961713Sgirish nxgep->rx_default_block_size, 173544961713Sgirish nxgep->sys_page_mask)); 173644961713Sgirish 173744961713Sgirish 173844961713Sgirish switch (nxgep->sys_page_sz) { 173944961713Sgirish default: 174044961713Sgirish nxgep->sys_page_sz = 0x1000; 174144961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 174244961713Sgirish nxgep->rx_default_block_size = 0x1000; 174344961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 174444961713Sgirish break; 174544961713Sgirish case 0x1000: 174644961713Sgirish nxgep->rx_default_block_size = 0x1000; 174744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 174844961713Sgirish break; 174944961713Sgirish case 0x2000: 175044961713Sgirish nxgep->rx_default_block_size = 0x2000; 175144961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 175244961713Sgirish break; 175344961713Sgirish case 0x4000: 175444961713Sgirish nxgep->rx_default_block_size = 0x4000; 175544961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 175644961713Sgirish break; 175744961713Sgirish case 0x8000: 175844961713Sgirish nxgep->rx_default_block_size = 0x8000; 175944961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 176044961713Sgirish break; 176144961713Sgirish } 176244961713Sgirish 176344961713Sgirish #ifndef USE_RX_BIG_BUF 176444961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 176544961713Sgirish #else 176644961713Sgirish nxgep->rx_default_block_size = 0x2000; 176744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 176844961713Sgirish #endif 176944961713Sgirish /* 177044961713Sgirish * Get the system DMA burst size. 177144961713Sgirish */ 177244961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 177344961713Sgirish DDI_DMA_DONTWAIT, 0, 177444961713Sgirish &nxgep->dmasparehandle); 177544961713Sgirish if (ddi_status != DDI_SUCCESS) { 177644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 177744961713Sgirish "ddi_dma_alloc_handle: failed " 177844961713Sgirish " status 0x%x", ddi_status)); 177944961713Sgirish goto nxge_get_soft_properties_exit; 178044961713Sgirish } 178144961713Sgirish 178244961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 178344961713Sgirish (caddr_t)nxgep->dmasparehandle, 178444961713Sgirish sizeof (nxgep->dmasparehandle), 178544961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 178644961713Sgirish DDI_DMA_DONTWAIT, 0, 178744961713Sgirish &cookie, &count); 178844961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 178944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 179044961713Sgirish "Binding spare handle to find system" 179144961713Sgirish " burstsize failed.")); 179244961713Sgirish ddi_status = DDI_FAILURE; 179344961713Sgirish goto nxge_get_soft_properties_fail1; 179444961713Sgirish } 179544961713Sgirish 179644961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 179744961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 179844961713Sgirish 179944961713Sgirish nxge_get_soft_properties_fail1: 180044961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 180144961713Sgirish 180244961713Sgirish nxge_get_soft_properties_exit: 180344961713Sgirish 180444961713Sgirish if (ddi_status != DDI_SUCCESS) 180544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 180644961713Sgirish 180744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 180844961713Sgirish "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 180944961713Sgirish return (status); 181044961713Sgirish } 181144961713Sgirish 181244961713Sgirish static nxge_status_t 181344961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 181444961713Sgirish { 181544961713Sgirish nxge_status_t status = NXGE_OK; 181644961713Sgirish 181744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 181844961713Sgirish 181944961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 182044961713Sgirish if (status != NXGE_OK) { 182144961713Sgirish return (NXGE_ERROR); 182244961713Sgirish } 182344961713Sgirish 182444961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 182544961713Sgirish if (status != NXGE_OK) { 182644961713Sgirish nxge_free_rx_mem_pool(nxgep); 182744961713Sgirish return (NXGE_ERROR); 182844961713Sgirish } 182944961713Sgirish 183044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 183144961713Sgirish return (NXGE_OK); 183244961713Sgirish } 183344961713Sgirish 183444961713Sgirish static void 183544961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 183644961713Sgirish { 183744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 183844961713Sgirish 183944961713Sgirish nxge_free_rx_mem_pool(nxgep); 184044961713Sgirish nxge_free_tx_mem_pool(nxgep); 184144961713Sgirish 184244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 184344961713Sgirish } 184444961713Sgirish 184544961713Sgirish static nxge_status_t 184644961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 184744961713Sgirish { 184844961713Sgirish int i, j; 184944961713Sgirish uint32_t ndmas, st_rdc; 185044961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 185144961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 185244961713Sgirish p_nxge_dma_pool_t dma_poolp; 185344961713Sgirish p_nxge_dma_common_t *dma_buf_p; 185444961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 185544961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 185644961713Sgirish size_t rx_buf_alloc_size; 185744961713Sgirish size_t rx_cntl_alloc_size; 185844961713Sgirish uint32_t *num_chunks; /* per dma */ 185944961713Sgirish nxge_status_t status = NXGE_OK; 186044961713Sgirish 186144961713Sgirish uint32_t nxge_port_rbr_size; 186244961713Sgirish uint32_t nxge_port_rbr_spare_size; 186344961713Sgirish uint32_t nxge_port_rcr_size; 186444961713Sgirish 186544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 186644961713Sgirish 186744961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 186844961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 186944961713Sgirish st_rdc = p_cfgp->start_rdc; 187044961713Sgirish ndmas = p_cfgp->max_rdcs; 187144961713Sgirish 187244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 187344961713Sgirish " nxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 187444961713Sgirish 187544961713Sgirish /* 187644961713Sgirish * Allocate memory for each receive DMA channel. 187744961713Sgirish */ 187844961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 187944961713Sgirish KM_SLEEP); 188044961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 188144961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 188244961713Sgirish 188344961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 188444961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 188544961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 188644961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 188744961713Sgirish 188844961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 188944961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 189044961713Sgirish 189144961713Sgirish /* 189244961713Sgirish * Assume that each DMA channel will be configured with default 189344961713Sgirish * block size. 189444961713Sgirish * rbr block counts are mod of batch count (16). 189544961713Sgirish */ 189644961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 189744961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 189844961713Sgirish 189944961713Sgirish if (!nxge_port_rbr_size) { 190044961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 190144961713Sgirish } 190244961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 190344961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 190444961713Sgirish (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 190544961713Sgirish } 190644961713Sgirish 190744961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 190844961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 190944961713Sgirish 191044961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 191144961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 191244961713Sgirish (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 191344961713Sgirish } 191430ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 191530ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 191630ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 191730ac2e7bSml "set to default %d", 191830ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 191930ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 192030ac2e7bSml } 192130ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 192230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 192330ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 192430ac2e7bSml "set to default %d", 192530ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 192630ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 192730ac2e7bSml } 192844961713Sgirish 192944961713Sgirish /* 193044961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 193144961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 193244961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 193344961713Sgirish * function). 193444961713Sgirish */ 193544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 193644961713Sgirish if (nxgep->niu_type == N2_NIU) { 193744961713Sgirish nxge_port_rbr_spare_size = 0; 193844961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 193944961713Sgirish (!ISP2(nxge_port_rbr_size))) { 194044961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 194144961713Sgirish } 194244961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 194344961713Sgirish (!ISP2(nxge_port_rcr_size))) { 194444961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 194544961713Sgirish } 194644961713Sgirish } 194744961713Sgirish #endif 194844961713Sgirish 194944961713Sgirish rx_buf_alloc_size = (nxgep->rx_default_block_size * 195044961713Sgirish (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 195144961713Sgirish 195244961713Sgirish /* 195344961713Sgirish * Addresses of receive block ring, receive completion ring and the 195444961713Sgirish * mailbox must be all cache-aligned (64 bytes). 195544961713Sgirish */ 195644961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 195744961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 195844961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 195944961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 196044961713Sgirish 196144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 196244961713Sgirish "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 196344961713Sgirish "nxge_port_rcr_size = %d " 196444961713Sgirish "rx_cntl_alloc_size = %d", 196544961713Sgirish nxge_port_rbr_size, nxge_port_rbr_spare_size, 196644961713Sgirish nxge_port_rcr_size, 196744961713Sgirish rx_cntl_alloc_size)); 196844961713Sgirish 196944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 197044961713Sgirish if (nxgep->niu_type == N2_NIU) { 197144961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 197244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 197344961713Sgirish "==> nxge_alloc_rx_mem_pool: " 197444961713Sgirish " must be power of 2")); 197544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 197644961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 197744961713Sgirish } 197844961713Sgirish 197944961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 198044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 198144961713Sgirish "==> nxge_alloc_rx_mem_pool: " 198244961713Sgirish " limit size to 4M")); 198344961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 198444961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 198544961713Sgirish } 198644961713Sgirish 198744961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 198844961713Sgirish rx_cntl_alloc_size = 0x2000; 198944961713Sgirish } 199044961713Sgirish } 199144961713Sgirish #endif 199244961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 199344961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 199444961713Sgirish 199544961713Sgirish /* 199644961713Sgirish * Allocate memory for receive buffers and descriptor rings. 199744961713Sgirish * Replace allocation functions with interface functions provided 199844961713Sgirish * by the partition manager when it is available. 199944961713Sgirish */ 200044961713Sgirish /* 200144961713Sgirish * Allocate memory for the receive buffer blocks. 200244961713Sgirish */ 200344961713Sgirish for (i = 0; i < ndmas; i++) { 200444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 200544961713Sgirish " nxge_alloc_rx_mem_pool to alloc mem: " 200644961713Sgirish " dma %d dma_buf_p %llx &dma_buf_p %llx", 200744961713Sgirish i, dma_buf_p[i], &dma_buf_p[i])); 200844961713Sgirish num_chunks[i] = 0; 200944961713Sgirish status = nxge_alloc_rx_buf_dma(nxgep, st_rdc, &dma_buf_p[i], 201044961713Sgirish rx_buf_alloc_size, 201144961713Sgirish nxgep->rx_default_block_size, &num_chunks[i]); 201244961713Sgirish if (status != NXGE_OK) { 201344961713Sgirish break; 201444961713Sgirish } 201544961713Sgirish st_rdc++; 201644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 201744961713Sgirish " nxge_alloc_rx_mem_pool DONE alloc mem: " 201844961713Sgirish "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 201944961713Sgirish dma_buf_p[i], &dma_buf_p[i])); 202044961713Sgirish } 202144961713Sgirish if (i < ndmas) { 202244961713Sgirish goto nxge_alloc_rx_mem_fail1; 202344961713Sgirish } 202444961713Sgirish /* 202544961713Sgirish * Allocate memory for descriptor rings and mailbox. 202644961713Sgirish */ 202744961713Sgirish st_rdc = p_cfgp->start_rdc; 202844961713Sgirish for (j = 0; j < ndmas; j++) { 202944961713Sgirish status = nxge_alloc_rx_cntl_dma(nxgep, st_rdc, &dma_cntl_p[j], 203044961713Sgirish rx_cntl_alloc_size); 203144961713Sgirish if (status != NXGE_OK) { 203244961713Sgirish break; 203344961713Sgirish } 203444961713Sgirish st_rdc++; 203544961713Sgirish } 203644961713Sgirish if (j < ndmas) { 203744961713Sgirish goto nxge_alloc_rx_mem_fail2; 203844961713Sgirish } 203944961713Sgirish 204044961713Sgirish dma_poolp->ndmas = ndmas; 204144961713Sgirish dma_poolp->num_chunks = num_chunks; 204244961713Sgirish dma_poolp->buf_allocated = B_TRUE; 204344961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 204444961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 204544961713Sgirish 204644961713Sgirish dma_cntl_poolp->ndmas = ndmas; 204744961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 204844961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 204944961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 205044961713Sgirish 205144961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 205244961713Sgirish 205344961713Sgirish nxge_alloc_rx_mem_fail2: 205444961713Sgirish /* Free control buffers */ 205544961713Sgirish j--; 205644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 205744961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 205844961713Sgirish for (; j >= 0; j--) { 205944961713Sgirish nxge_free_rx_cntl_dma(nxgep, 206056d930aeSspeer (p_nxge_dma_common_t)dma_cntl_p[j]); 206144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 206244961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", 206344961713Sgirish j)); 206444961713Sgirish } 206544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 206644961713Sgirish "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 206744961713Sgirish 206844961713Sgirish nxge_alloc_rx_mem_fail1: 206944961713Sgirish /* Free data buffers */ 207044961713Sgirish i--; 207144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 207244961713Sgirish "==> nxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 207344961713Sgirish for (; i >= 0; i--) { 207444961713Sgirish nxge_free_rx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 207544961713Sgirish num_chunks[i]); 207644961713Sgirish } 207744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 207844961713Sgirish "==> nxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 207944961713Sgirish 208044961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 208144961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 208244961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 208344961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 208444961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 208544961713Sgirish 208644961713Sgirish nxge_alloc_rx_mem_pool_exit: 208744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 208844961713Sgirish "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 208944961713Sgirish 209044961713Sgirish return (status); 209144961713Sgirish } 209244961713Sgirish 209344961713Sgirish static void 209444961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 209544961713Sgirish { 209644961713Sgirish uint32_t i, ndmas; 209744961713Sgirish p_nxge_dma_pool_t dma_poolp; 209844961713Sgirish p_nxge_dma_common_t *dma_buf_p; 209944961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 210044961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 210144961713Sgirish uint32_t *num_chunks; 210244961713Sgirish 210344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 210444961713Sgirish 210544961713Sgirish dma_poolp = nxgep->rx_buf_pool_p; 210644961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 210744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 210844961713Sgirish "<== nxge_free_rx_mem_pool " 210944961713Sgirish "(null rx buf pool or buf not allocated")); 211044961713Sgirish return; 211144961713Sgirish } 211244961713Sgirish 211344961713Sgirish dma_cntl_poolp = nxgep->rx_cntl_pool_p; 211444961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 211544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 211644961713Sgirish "<== nxge_free_rx_mem_pool " 211744961713Sgirish "(null rx cntl buf pool or cntl buf not allocated")); 211844961713Sgirish return; 211944961713Sgirish } 212044961713Sgirish 212144961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 212244961713Sgirish num_chunks = dma_poolp->num_chunks; 212344961713Sgirish 212444961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 212544961713Sgirish ndmas = dma_cntl_poolp->ndmas; 212644961713Sgirish 212744961713Sgirish for (i = 0; i < ndmas; i++) { 212844961713Sgirish nxge_free_rx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 212944961713Sgirish } 213044961713Sgirish 213144961713Sgirish for (i = 0; i < ndmas; i++) { 213244961713Sgirish nxge_free_rx_cntl_dma(nxgep, dma_cntl_p[i]); 213344961713Sgirish } 213444961713Sgirish 213544961713Sgirish for (i = 0; i < ndmas; i++) { 213644961713Sgirish KMEM_FREE(dma_buf_p[i], 213744961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 213844961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 213944961713Sgirish } 214044961713Sgirish 214144961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 214244961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 214344961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 214444961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 214544961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 214644961713Sgirish 214744961713Sgirish nxgep->rx_buf_pool_p = NULL; 214844961713Sgirish nxgep->rx_cntl_pool_p = NULL; 214944961713Sgirish 215044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 215144961713Sgirish } 215244961713Sgirish 215344961713Sgirish 215444961713Sgirish static nxge_status_t 215544961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 215644961713Sgirish p_nxge_dma_common_t *dmap, 215744961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 215844961713Sgirish { 215944961713Sgirish p_nxge_dma_common_t rx_dmap; 216044961713Sgirish nxge_status_t status = NXGE_OK; 216144961713Sgirish size_t total_alloc_size; 216244961713Sgirish size_t allocated = 0; 216344961713Sgirish int i, size_index, array_size; 216444961713Sgirish 216544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 216644961713Sgirish 216744961713Sgirish rx_dmap = (p_nxge_dma_common_t) 216844961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 216944961713Sgirish KM_SLEEP); 217044961713Sgirish 217144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 217244961713Sgirish " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 217344961713Sgirish dma_channel, alloc_size, block_size, dmap)); 217444961713Sgirish 217544961713Sgirish total_alloc_size = alloc_size; 217644961713Sgirish 217744961713Sgirish #if defined(RX_USE_RECLAIM_POST) 217844961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 217944961713Sgirish #endif 218044961713Sgirish 218144961713Sgirish i = 0; 218244961713Sgirish size_index = 0; 218344961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 218444961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 218544961713Sgirish (size_index < array_size)) 218644961713Sgirish size_index++; 218744961713Sgirish if (size_index >= array_size) { 218844961713Sgirish size_index = array_size - 1; 218944961713Sgirish } 219044961713Sgirish 219144961713Sgirish while ((allocated < total_alloc_size) && 219244961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 219344961713Sgirish rx_dmap[i].dma_chunk_index = i; 219444961713Sgirish rx_dmap[i].block_size = block_size; 219544961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 219644961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 219744961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 219844961713Sgirish rx_dmap[i].dma_channel = dma_channel; 219944961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 220044961713Sgirish 220144961713Sgirish /* 220244961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 220344961713Sgirish * needs to call Hypervisor api to set up 220444961713Sgirish * logical pages. 220544961713Sgirish */ 220644961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 220744961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 220844961713Sgirish } 220944961713Sgirish 221044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 221144961713Sgirish "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 221244961713Sgirish "i %d nblocks %d alength %d", 221344961713Sgirish dma_channel, i, &rx_dmap[i], block_size, 221444961713Sgirish i, rx_dmap[i].nblocks, 221544961713Sgirish rx_dmap[i].alength)); 221644961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 221744961713Sgirish &nxge_rx_dma_attr, 221844961713Sgirish rx_dmap[i].alength, 221944961713Sgirish &nxge_dev_buf_dma_acc_attr, 222044961713Sgirish DDI_DMA_READ | DDI_DMA_STREAMING, 222144961713Sgirish (p_nxge_dma_common_t)(&rx_dmap[i])); 222244961713Sgirish if (status != NXGE_OK) { 222344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 222444961713Sgirish " nxge_alloc_rx_buf_dma: Alloc Failed ")); 222544961713Sgirish size_index--; 222644961713Sgirish } else { 222744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 222844961713Sgirish " alloc_rx_buf_dma allocated rdc %d " 222944961713Sgirish "chunk %d size %x dvma %x bufp %llx ", 223044961713Sgirish dma_channel, i, rx_dmap[i].alength, 223144961713Sgirish rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 223244961713Sgirish i++; 223344961713Sgirish allocated += alloc_sizes[size_index]; 223444961713Sgirish } 223544961713Sgirish } 223644961713Sgirish 223744961713Sgirish 223844961713Sgirish if (allocated < total_alloc_size) { 223930ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 224030ac2e7bSml "==> nxge_alloc_rx_buf_dma: not enough for channe %d " 224130ac2e7bSml "allocated 0x%x requested 0x%x", 224230ac2e7bSml dma_channel, 224330ac2e7bSml allocated, total_alloc_size)); 224430ac2e7bSml status = NXGE_ERROR; 224544961713Sgirish goto nxge_alloc_rx_mem_fail1; 224644961713Sgirish } 224744961713Sgirish 224830ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 224930ac2e7bSml "==> nxge_alloc_rx_buf_dma: Allocated for channe %d " 225030ac2e7bSml "allocated 0x%x requested 0x%x", 225130ac2e7bSml dma_channel, 225230ac2e7bSml allocated, total_alloc_size)); 225330ac2e7bSml 225444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 225544961713Sgirish " alloc_rx_buf_dma rdc %d allocated %d chunks", 225644961713Sgirish dma_channel, i)); 225744961713Sgirish *num_chunks = i; 225844961713Sgirish *dmap = rx_dmap; 225944961713Sgirish 226044961713Sgirish goto nxge_alloc_rx_mem_exit; 226144961713Sgirish 226244961713Sgirish nxge_alloc_rx_mem_fail1: 226344961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 226444961713Sgirish 226544961713Sgirish nxge_alloc_rx_mem_exit: 226644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 226744961713Sgirish "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 226844961713Sgirish 226944961713Sgirish return (status); 227044961713Sgirish } 227144961713Sgirish 227244961713Sgirish /*ARGSUSED*/ 227344961713Sgirish static void 227444961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 227544961713Sgirish uint32_t num_chunks) 227644961713Sgirish { 227744961713Sgirish int i; 227844961713Sgirish 227944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 228044961713Sgirish "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 228144961713Sgirish 228244961713Sgirish for (i = 0; i < num_chunks; i++) { 228344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 228444961713Sgirish "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 228544961713Sgirish i, dmap)); 228644961713Sgirish nxge_dma_mem_free(dmap++); 228744961713Sgirish } 228844961713Sgirish 228944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 229044961713Sgirish } 229144961713Sgirish 229244961713Sgirish /*ARGSUSED*/ 229344961713Sgirish static nxge_status_t 229444961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 229544961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 229644961713Sgirish { 229744961713Sgirish p_nxge_dma_common_t rx_dmap; 229844961713Sgirish nxge_status_t status = NXGE_OK; 229944961713Sgirish 230044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 230144961713Sgirish 230244961713Sgirish rx_dmap = (p_nxge_dma_common_t) 230344961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 230444961713Sgirish 230544961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 230644961713Sgirish 230744961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 230844961713Sgirish &nxge_desc_dma_attr, 230944961713Sgirish size, 231044961713Sgirish &nxge_dev_desc_dma_acc_attr, 231144961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 231244961713Sgirish rx_dmap); 231344961713Sgirish if (status != NXGE_OK) { 231444961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 231544961713Sgirish } 231644961713Sgirish 231744961713Sgirish *dmap = rx_dmap; 231844961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 231944961713Sgirish 232044961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 232144961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 232244961713Sgirish 232344961713Sgirish nxge_alloc_rx_cntl_dma_exit: 232444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 232544961713Sgirish "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 232644961713Sgirish 232744961713Sgirish return (status); 232844961713Sgirish } 232944961713Sgirish 233044961713Sgirish /*ARGSUSED*/ 233144961713Sgirish static void 233244961713Sgirish nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 233344961713Sgirish { 233444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 233544961713Sgirish 233644961713Sgirish nxge_dma_mem_free(dmap); 233744961713Sgirish 233844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 233944961713Sgirish } 234044961713Sgirish 234144961713Sgirish static nxge_status_t 234244961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 234344961713Sgirish { 234444961713Sgirish nxge_status_t status = NXGE_OK; 234544961713Sgirish int i, j; 234644961713Sgirish uint32_t ndmas, st_tdc; 234744961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 234844961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 234944961713Sgirish p_nxge_dma_pool_t dma_poolp; 235044961713Sgirish p_nxge_dma_common_t *dma_buf_p; 235144961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 235244961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 235344961713Sgirish size_t tx_buf_alloc_size; 235444961713Sgirish size_t tx_cntl_alloc_size; 235544961713Sgirish uint32_t *num_chunks; /* per dma */ 23561f8914d5Sml uint32_t bcopy_thresh; 235744961713Sgirish 235844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 235944961713Sgirish 236044961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 236144961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 236244961713Sgirish st_tdc = p_cfgp->start_tdc; 236344961713Sgirish ndmas = p_cfgp->max_tdcs; 236444961713Sgirish 236544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool: " 236644961713Sgirish "p_cfgp 0x%016llx start_tdc %d ndmas %d nxgep->max_tdcs %d", 236744961713Sgirish p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, nxgep->max_tdcs)); 236844961713Sgirish /* 236944961713Sgirish * Allocate memory for each transmit DMA channel. 237044961713Sgirish */ 237144961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 237244961713Sgirish KM_SLEEP); 237344961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 237444961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 237544961713Sgirish 237644961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 237744961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 237844961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 237944961713Sgirish sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP); 238044961713Sgirish 238130ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 238230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 238330ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 238430ac2e7bSml "set to default %d", 238530ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 238630ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 238730ac2e7bSml } 238830ac2e7bSml 238944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 239044961713Sgirish /* 239144961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 239244961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 239344961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 239444961713Sgirish * function). The transmit ring is limited to 8K (includes the 239544961713Sgirish * mailbox). 239644961713Sgirish */ 239744961713Sgirish if (nxgep->niu_type == N2_NIU) { 239844961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 239944961713Sgirish (!ISP2(nxge_tx_ring_size))) { 240044961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 240144961713Sgirish } 240244961713Sgirish } 240344961713Sgirish #endif 240444961713Sgirish 240544961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 240644961713Sgirish 240744961713Sgirish /* 240844961713Sgirish * Assume that each DMA channel will be configured with default 240944961713Sgirish * transmit bufer size for copying transmit data. 241044961713Sgirish * (For packet payload over this limit, packets will not be 241144961713Sgirish * copied.) 241244961713Sgirish */ 24131f8914d5Sml if (nxgep->niu_type == N2_NIU) { 24141f8914d5Sml bcopy_thresh = TX_BCOPY_SIZE; 24151f8914d5Sml } else { 24161f8914d5Sml bcopy_thresh = nxge_bcopy_thresh; 24171f8914d5Sml } 24181f8914d5Sml tx_buf_alloc_size = (bcopy_thresh * nxge_tx_ring_size); 241944961713Sgirish 242044961713Sgirish /* 242144961713Sgirish * Addresses of transmit descriptor ring and the 242244961713Sgirish * mailbox must be all cache-aligned (64 bytes). 242344961713Sgirish */ 242444961713Sgirish tx_cntl_alloc_size = nxge_tx_ring_size; 242544961713Sgirish tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 242644961713Sgirish tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 242744961713Sgirish 242844961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 242944961713Sgirish if (nxgep->niu_type == N2_NIU) { 243044961713Sgirish if (!ISP2(tx_buf_alloc_size)) { 243144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 243244961713Sgirish "==> nxge_alloc_tx_mem_pool: " 243344961713Sgirish " must be power of 2")); 243444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 243544961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 243644961713Sgirish } 243744961713Sgirish 243844961713Sgirish if (tx_buf_alloc_size > (1 << 22)) { 243944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 244044961713Sgirish "==> nxge_alloc_tx_mem_pool: " 244144961713Sgirish " limit size to 4M")); 244244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 244344961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 244444961713Sgirish } 244544961713Sgirish 244644961713Sgirish if (tx_cntl_alloc_size < 0x2000) { 244744961713Sgirish tx_cntl_alloc_size = 0x2000; 244844961713Sgirish } 244944961713Sgirish } 245044961713Sgirish #endif 245144961713Sgirish 245244961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 245344961713Sgirish sizeof (uint32_t) * ndmas, KM_SLEEP); 245444961713Sgirish 245544961713Sgirish /* 245644961713Sgirish * Allocate memory for transmit buffers and descriptor rings. 245744961713Sgirish * Replace allocation functions with interface functions provided 245844961713Sgirish * by the partition manager when it is available. 245944961713Sgirish * 246044961713Sgirish * Allocate memory for the transmit buffer pool. 246144961713Sgirish */ 246244961713Sgirish for (i = 0; i < ndmas; i++) { 246344961713Sgirish num_chunks[i] = 0; 246444961713Sgirish status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i], 246544961713Sgirish tx_buf_alloc_size, 24661f8914d5Sml bcopy_thresh, &num_chunks[i]); 246744961713Sgirish if (status != NXGE_OK) { 246844961713Sgirish break; 246944961713Sgirish } 247044961713Sgirish st_tdc++; 247144961713Sgirish } 247244961713Sgirish if (i < ndmas) { 247344961713Sgirish goto nxge_alloc_tx_mem_pool_fail1; 247444961713Sgirish } 247544961713Sgirish 247644961713Sgirish st_tdc = p_cfgp->start_tdc; 247744961713Sgirish /* 247844961713Sgirish * Allocate memory for descriptor rings and mailbox. 247944961713Sgirish */ 248044961713Sgirish for (j = 0; j < ndmas; j++) { 248144961713Sgirish status = nxge_alloc_tx_cntl_dma(nxgep, st_tdc, &dma_cntl_p[j], 248244961713Sgirish tx_cntl_alloc_size); 248344961713Sgirish if (status != NXGE_OK) { 248444961713Sgirish break; 248544961713Sgirish } 248644961713Sgirish st_tdc++; 248744961713Sgirish } 248844961713Sgirish if (j < ndmas) { 248944961713Sgirish goto nxge_alloc_tx_mem_pool_fail2; 249044961713Sgirish } 249144961713Sgirish 249244961713Sgirish dma_poolp->ndmas = ndmas; 249344961713Sgirish dma_poolp->num_chunks = num_chunks; 249444961713Sgirish dma_poolp->buf_allocated = B_TRUE; 249544961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 249644961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 249744961713Sgirish 249844961713Sgirish dma_cntl_poolp->ndmas = ndmas; 249944961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 250044961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 250144961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 250244961713Sgirish 250344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 250444961713Sgirish "==> nxge_alloc_tx_mem_pool: start_tdc %d " 250544961713Sgirish "ndmas %d poolp->ndmas %d", 250644961713Sgirish st_tdc, ndmas, dma_poolp->ndmas)); 250744961713Sgirish 250844961713Sgirish goto nxge_alloc_tx_mem_pool_exit; 250944961713Sgirish 251044961713Sgirish nxge_alloc_tx_mem_pool_fail2: 251144961713Sgirish /* Free control buffers */ 251244961713Sgirish j--; 251344961713Sgirish for (; j >= 0; j--) { 251444961713Sgirish nxge_free_tx_cntl_dma(nxgep, 251556d930aeSspeer (p_nxge_dma_common_t)dma_cntl_p[j]); 251644961713Sgirish } 251744961713Sgirish 251844961713Sgirish nxge_alloc_tx_mem_pool_fail1: 251944961713Sgirish /* Free data buffers */ 252044961713Sgirish i--; 252144961713Sgirish for (; i >= 0; i--) { 252244961713Sgirish nxge_free_tx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i], 252344961713Sgirish num_chunks[i]); 252444961713Sgirish } 252544961713Sgirish 252644961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 252744961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 252844961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 252944961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 253044961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 253144961713Sgirish 253244961713Sgirish nxge_alloc_tx_mem_pool_exit: 253344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 253444961713Sgirish "<== nxge_alloc_tx_mem_pool:status 0x%08x", status)); 253544961713Sgirish 253644961713Sgirish return (status); 253744961713Sgirish } 253844961713Sgirish 253944961713Sgirish static nxge_status_t 254044961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 254144961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 254244961713Sgirish size_t block_size, uint32_t *num_chunks) 254344961713Sgirish { 254444961713Sgirish p_nxge_dma_common_t tx_dmap; 254544961713Sgirish nxge_status_t status = NXGE_OK; 254644961713Sgirish size_t total_alloc_size; 254744961713Sgirish size_t allocated = 0; 254844961713Sgirish int i, size_index, array_size; 254944961713Sgirish 255044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 255144961713Sgirish 255244961713Sgirish tx_dmap = (p_nxge_dma_common_t) 255344961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 255444961713Sgirish KM_SLEEP); 255544961713Sgirish 255644961713Sgirish total_alloc_size = alloc_size; 255744961713Sgirish i = 0; 255844961713Sgirish size_index = 0; 255944961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 256044961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 256144961713Sgirish (size_index < array_size)) 256244961713Sgirish size_index++; 256344961713Sgirish if (size_index >= array_size) { 256444961713Sgirish size_index = array_size - 1; 256544961713Sgirish } 256644961713Sgirish 256744961713Sgirish while ((allocated < total_alloc_size) && 256844961713Sgirish (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 256944961713Sgirish 257044961713Sgirish tx_dmap[i].dma_chunk_index = i; 257144961713Sgirish tx_dmap[i].block_size = block_size; 257244961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 257344961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 257444961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 257544961713Sgirish tx_dmap[i].dma_channel = dma_channel; 257644961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 257744961713Sgirish 257844961713Sgirish /* 257944961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 258044961713Sgirish * needs to call Hypervisor api to set up 258144961713Sgirish * logical pages. 258244961713Sgirish */ 258344961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 258444961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 258544961713Sgirish } 258644961713Sgirish 258744961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 258844961713Sgirish &nxge_tx_dma_attr, 258944961713Sgirish tx_dmap[i].alength, 259044961713Sgirish &nxge_dev_buf_dma_acc_attr, 259144961713Sgirish DDI_DMA_WRITE | DDI_DMA_STREAMING, 259244961713Sgirish (p_nxge_dma_common_t)(&tx_dmap[i])); 259344961713Sgirish if (status != NXGE_OK) { 259444961713Sgirish size_index--; 259544961713Sgirish } else { 259644961713Sgirish i++; 259744961713Sgirish allocated += alloc_sizes[size_index]; 259844961713Sgirish } 259944961713Sgirish } 260044961713Sgirish 260144961713Sgirish if (allocated < total_alloc_size) { 260230ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 260330ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 260430ac2e7bSml "allocated 0x%x requested 0x%x", 260530ac2e7bSml dma_channel, 260630ac2e7bSml allocated, total_alloc_size)); 260730ac2e7bSml status = NXGE_ERROR; 260844961713Sgirish goto nxge_alloc_tx_mem_fail1; 260944961713Sgirish } 261044961713Sgirish 261130ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 261230ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 261330ac2e7bSml "allocated 0x%x requested 0x%x", 261430ac2e7bSml dma_channel, 261530ac2e7bSml allocated, total_alloc_size)); 261630ac2e7bSml 261744961713Sgirish *num_chunks = i; 261844961713Sgirish *dmap = tx_dmap; 261944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 262044961713Sgirish "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 262144961713Sgirish *dmap, i)); 262244961713Sgirish goto nxge_alloc_tx_mem_exit; 262344961713Sgirish 262444961713Sgirish nxge_alloc_tx_mem_fail1: 262544961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 262644961713Sgirish 262744961713Sgirish nxge_alloc_tx_mem_exit: 262844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 262944961713Sgirish "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 263044961713Sgirish 263144961713Sgirish return (status); 263244961713Sgirish } 263344961713Sgirish 263444961713Sgirish /*ARGSUSED*/ 263544961713Sgirish static void 263644961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 263744961713Sgirish uint32_t num_chunks) 263844961713Sgirish { 263944961713Sgirish int i; 264044961713Sgirish 264144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 264244961713Sgirish 264344961713Sgirish for (i = 0; i < num_chunks; i++) { 264444961713Sgirish nxge_dma_mem_free(dmap++); 264544961713Sgirish } 264644961713Sgirish 264744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 264844961713Sgirish } 264944961713Sgirish 265044961713Sgirish /*ARGSUSED*/ 265144961713Sgirish static nxge_status_t 265244961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 265344961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 265444961713Sgirish { 265544961713Sgirish p_nxge_dma_common_t tx_dmap; 265644961713Sgirish nxge_status_t status = NXGE_OK; 265744961713Sgirish 265844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 265944961713Sgirish tx_dmap = (p_nxge_dma_common_t) 266044961713Sgirish KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 266144961713Sgirish 266244961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 266344961713Sgirish 266444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 266544961713Sgirish &nxge_desc_dma_attr, 266644961713Sgirish size, 266744961713Sgirish &nxge_dev_desc_dma_acc_attr, 266844961713Sgirish DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 266944961713Sgirish tx_dmap); 267044961713Sgirish if (status != NXGE_OK) { 267144961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 267244961713Sgirish } 267344961713Sgirish 267444961713Sgirish *dmap = tx_dmap; 267544961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 267644961713Sgirish 267744961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 267844961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 267944961713Sgirish 268044961713Sgirish nxge_alloc_tx_cntl_dma_exit: 268144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 268244961713Sgirish "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 268344961713Sgirish 268444961713Sgirish return (status); 268544961713Sgirish } 268644961713Sgirish 268744961713Sgirish /*ARGSUSED*/ 268844961713Sgirish static void 268944961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 269044961713Sgirish { 269144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 269244961713Sgirish 269344961713Sgirish nxge_dma_mem_free(dmap); 269444961713Sgirish 269544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 269644961713Sgirish } 269744961713Sgirish 269844961713Sgirish static void 269944961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 270044961713Sgirish { 270144961713Sgirish uint32_t i, ndmas; 270244961713Sgirish p_nxge_dma_pool_t dma_poolp; 270344961713Sgirish p_nxge_dma_common_t *dma_buf_p; 270444961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 270544961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 270644961713Sgirish uint32_t *num_chunks; 270744961713Sgirish 270844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_free_tx_mem_pool")); 270944961713Sgirish 271044961713Sgirish dma_poolp = nxgep->tx_buf_pool_p; 271144961713Sgirish if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 271244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 271344961713Sgirish "<== nxge_free_tx_mem_pool " 271444961713Sgirish "(null rx buf pool or buf not allocated")); 271544961713Sgirish return; 271644961713Sgirish } 271744961713Sgirish 271844961713Sgirish dma_cntl_poolp = nxgep->tx_cntl_pool_p; 271944961713Sgirish if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 272044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 272144961713Sgirish "<== nxge_free_tx_mem_pool " 272244961713Sgirish "(null tx cntl buf pool or cntl buf not allocated")); 272344961713Sgirish return; 272444961713Sgirish } 272544961713Sgirish 272644961713Sgirish dma_buf_p = dma_poolp->dma_buf_pool_p; 272744961713Sgirish num_chunks = dma_poolp->num_chunks; 272844961713Sgirish 272944961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 273044961713Sgirish ndmas = dma_cntl_poolp->ndmas; 273144961713Sgirish 273244961713Sgirish for (i = 0; i < ndmas; i++) { 273344961713Sgirish nxge_free_tx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]); 273444961713Sgirish } 273544961713Sgirish 273644961713Sgirish for (i = 0; i < ndmas; i++) { 273744961713Sgirish nxge_free_tx_cntl_dma(nxgep, dma_cntl_p[i]); 273844961713Sgirish } 273944961713Sgirish 274044961713Sgirish for (i = 0; i < ndmas; i++) { 274144961713Sgirish KMEM_FREE(dma_buf_p[i], 274244961713Sgirish sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 274344961713Sgirish KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t)); 274444961713Sgirish } 274544961713Sgirish 274644961713Sgirish KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 274744961713Sgirish KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t)); 274844961713Sgirish KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t)); 274944961713Sgirish KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t)); 275044961713Sgirish KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t)); 275144961713Sgirish 275244961713Sgirish nxgep->tx_buf_pool_p = NULL; 275344961713Sgirish nxgep->tx_cntl_pool_p = NULL; 275444961713Sgirish 275544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_free_tx_mem_pool")); 275644961713Sgirish } 275744961713Sgirish 275844961713Sgirish /*ARGSUSED*/ 275944961713Sgirish static nxge_status_t 276044961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 276144961713Sgirish struct ddi_dma_attr *dma_attrp, 276244961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 276344961713Sgirish p_nxge_dma_common_t dma_p) 276444961713Sgirish { 276544961713Sgirish caddr_t kaddrp; 276644961713Sgirish int ddi_status = DDI_SUCCESS; 276744961713Sgirish boolean_t contig_alloc_type; 276844961713Sgirish 276944961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 277044961713Sgirish 277144961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 277244961713Sgirish /* 277344961713Sgirish * contig_alloc_type for contiguous memory only allowed 277444961713Sgirish * for N2/NIU. 277544961713Sgirish */ 277644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 277744961713Sgirish "nxge_dma_mem_alloc: alloc type not allows (%d)", 277844961713Sgirish dma_p->contig_alloc_type)); 277944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 278044961713Sgirish } 278144961713Sgirish 278244961713Sgirish dma_p->dma_handle = NULL; 278344961713Sgirish dma_p->acc_handle = NULL; 278444961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 278544961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 278644961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 278744961713Sgirish DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 278844961713Sgirish if (ddi_status != DDI_SUCCESS) { 278944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 279044961713Sgirish "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 279144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 279244961713Sgirish } 279344961713Sgirish 279444961713Sgirish switch (contig_alloc_type) { 279544961713Sgirish case B_FALSE: 279644961713Sgirish ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, 279744961713Sgirish acc_attr_p, 279844961713Sgirish xfer_flags, 279944961713Sgirish DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 280044961713Sgirish &dma_p->acc_handle); 280144961713Sgirish if (ddi_status != DDI_SUCCESS) { 280244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280344961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 280444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 280544961713Sgirish dma_p->dma_handle = NULL; 280644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 280744961713Sgirish } 280844961713Sgirish if (dma_p->alength < length) { 280944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 281044961713Sgirish "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 281144961713Sgirish "< length.")); 281244961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 281344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 281444961713Sgirish dma_p->acc_handle = NULL; 281544961713Sgirish dma_p->dma_handle = NULL; 281644961713Sgirish return (NXGE_ERROR); 281744961713Sgirish } 281844961713Sgirish 281944961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 282044961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 282144961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 282244961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 282344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 282444961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 282544961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 282644961713Sgirish dma_p->ncookies)); 282744961713Sgirish if (dma_p->acc_handle) { 282844961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 282944961713Sgirish dma_p->acc_handle = NULL; 283044961713Sgirish } 283144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 283244961713Sgirish dma_p->dma_handle = NULL; 283344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 283444961713Sgirish } 283544961713Sgirish 283644961713Sgirish if (dma_p->ncookies != 1) { 283744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 283844961713Sgirish "nxge_dma_mem_alloc:ddi_dma_addr_bind " 283944961713Sgirish "> 1 cookie" 284044961713Sgirish "(staus 0x%x ncookies %d.)", ddi_status, 284144961713Sgirish dma_p->ncookies)); 284244961713Sgirish if (dma_p->acc_handle) { 284344961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 284444961713Sgirish dma_p->acc_handle = NULL; 284544961713Sgirish } 284656d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 284744961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 284844961713Sgirish dma_p->dma_handle = NULL; 284944961713Sgirish return (NXGE_ERROR); 285044961713Sgirish } 285144961713Sgirish break; 285244961713Sgirish 285344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 285444961713Sgirish case B_TRUE: 285544961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 285644961713Sgirish if (kaddrp == NULL) { 285744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 285844961713Sgirish "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 285944961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 286044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 286144961713Sgirish } 286244961713Sgirish 286344961713Sgirish dma_p->alength = length; 286444961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 286544961713Sgirish kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 286644961713Sgirish &dma_p->dma_cookie, &dma_p->ncookies); 286744961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 286844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 286944961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind failed " 287044961713Sgirish "(status 0x%x ncookies %d.)", ddi_status, 287144961713Sgirish dma_p->ncookies)); 287244961713Sgirish 287344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 287444961713Sgirish "==> nxge_dma_mem_alloc: (not mapped)" 287544961713Sgirish "length %lu (0x%x) " 287644961713Sgirish "free contig kaddrp $%p " 287744961713Sgirish "va_to_pa $%p", 287844961713Sgirish length, length, 287944961713Sgirish kaddrp, 288044961713Sgirish va_to_pa(kaddrp))); 288144961713Sgirish 288244961713Sgirish 288344961713Sgirish contig_mem_free((void *)kaddrp, length); 288444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 288544961713Sgirish 288644961713Sgirish dma_p->dma_handle = NULL; 288744961713Sgirish dma_p->acc_handle = NULL; 288844961713Sgirish dma_p->alength = NULL; 288944961713Sgirish dma_p->kaddrp = NULL; 289044961713Sgirish 289144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 289244961713Sgirish } 289344961713Sgirish 289444961713Sgirish if (dma_p->ncookies != 1 || 289544961713Sgirish (dma_p->dma_cookie.dmac_laddress == NULL)) { 289644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 289744961713Sgirish "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 289844961713Sgirish "cookie or " 289944961713Sgirish "dmac_laddress is NULL $%p size %d " 290044961713Sgirish " (status 0x%x ncookies %d.)", 290144961713Sgirish ddi_status, 290244961713Sgirish dma_p->dma_cookie.dmac_laddress, 290344961713Sgirish dma_p->dma_cookie.dmac_size, 290444961713Sgirish dma_p->ncookies)); 290544961713Sgirish 290644961713Sgirish contig_mem_free((void *)kaddrp, length); 290756d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 290844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 290944961713Sgirish 291044961713Sgirish dma_p->alength = 0; 291144961713Sgirish dma_p->dma_handle = NULL; 291244961713Sgirish dma_p->acc_handle = NULL; 291344961713Sgirish dma_p->kaddrp = NULL; 291444961713Sgirish 291544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 291644961713Sgirish } 291744961713Sgirish break; 291844961713Sgirish 291944961713Sgirish #else 292044961713Sgirish case B_TRUE: 292144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 292244961713Sgirish "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 292344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 292444961713Sgirish #endif 292544961713Sgirish } 292644961713Sgirish 292744961713Sgirish dma_p->kaddrp = kaddrp; 292844961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 292944961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 2930adfcba55Sjoycey #if defined(__i386) 2931adfcba55Sjoycey dma_p->ioaddr_pp = 2932adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 2933adfcba55Sjoycey #else 293444961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 2935adfcba55Sjoycey #endif 293644961713Sgirish dma_p->last_ioaddr_pp = 2937adfcba55Sjoycey #if defined(__i386) 2938adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 2939adfcba55Sjoycey #else 294044961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress + 2941adfcba55Sjoycey #endif 294244961713Sgirish dma_p->alength - RXBUF_64B_ALIGNED; 294344961713Sgirish 294444961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 294544961713Sgirish 294644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 294744961713Sgirish dma_p->orig_ioaddr_pp = 294844961713Sgirish (unsigned char *)dma_p->dma_cookie.dmac_laddress; 294944961713Sgirish dma_p->orig_alength = length; 295044961713Sgirish dma_p->orig_kaddrp = kaddrp; 295144961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 295244961713Sgirish #endif 295344961713Sgirish 295444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 295544961713Sgirish "dma buffer allocated: dma_p $%p " 295644961713Sgirish "return dmac_ladress from cookie $%p cookie dmac_size %d " 295744961713Sgirish "dma_p->ioaddr_p $%p " 295844961713Sgirish "dma_p->orig_ioaddr_p $%p " 295944961713Sgirish "orig_vatopa $%p " 296044961713Sgirish "alength %d (0x%x) " 296144961713Sgirish "kaddrp $%p " 296244961713Sgirish "length %d (0x%x)", 296344961713Sgirish dma_p, 296444961713Sgirish dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 296544961713Sgirish dma_p->ioaddr_pp, 296644961713Sgirish dma_p->orig_ioaddr_pp, 296744961713Sgirish dma_p->orig_vatopa, 296844961713Sgirish dma_p->alength, dma_p->alength, 296944961713Sgirish kaddrp, 297044961713Sgirish length, length)); 297144961713Sgirish 297244961713Sgirish return (NXGE_OK); 297344961713Sgirish } 297444961713Sgirish 297544961713Sgirish static void 297644961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 297744961713Sgirish { 297844961713Sgirish if (dma_p->dma_handle != NULL) { 297944961713Sgirish if (dma_p->ncookies) { 298044961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 298144961713Sgirish dma_p->ncookies = 0; 298244961713Sgirish } 298344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 298444961713Sgirish dma_p->dma_handle = NULL; 298544961713Sgirish } 298644961713Sgirish 298744961713Sgirish if (dma_p->acc_handle != NULL) { 298844961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 298944961713Sgirish dma_p->acc_handle = NULL; 299044961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 299144961713Sgirish } 299244961713Sgirish 299344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 299444961713Sgirish if (dma_p->contig_alloc_type && 299544961713Sgirish dma_p->orig_kaddrp && dma_p->orig_alength) { 299644961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 299744961713Sgirish "kaddrp $%p (orig_kaddrp $%p)" 299844961713Sgirish "mem type %d ", 299944961713Sgirish "orig_alength %d " 300044961713Sgirish "alength 0x%x (%d)", 300144961713Sgirish dma_p->kaddrp, 300244961713Sgirish dma_p->orig_kaddrp, 300344961713Sgirish dma_p->contig_alloc_type, 300444961713Sgirish dma_p->orig_alength, 300544961713Sgirish dma_p->alength, dma_p->alength)); 300644961713Sgirish 300744961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 300844961713Sgirish dma_p->orig_alength = NULL; 300944961713Sgirish dma_p->orig_kaddrp = NULL; 301044961713Sgirish dma_p->contig_alloc_type = B_FALSE; 301144961713Sgirish } 301244961713Sgirish #endif 301344961713Sgirish dma_p->kaddrp = NULL; 301444961713Sgirish dma_p->alength = NULL; 301544961713Sgirish } 301644961713Sgirish 301744961713Sgirish /* 301844961713Sgirish * nxge_m_start() -- start transmitting and receiving. 301944961713Sgirish * 302044961713Sgirish * This function is called by the MAC layer when the first 302144961713Sgirish * stream is open to prepare the hardware ready for sending 302244961713Sgirish * and transmitting packets. 302344961713Sgirish */ 302444961713Sgirish static int 302544961713Sgirish nxge_m_start(void *arg) 302644961713Sgirish { 302744961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 302844961713Sgirish 302944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 303044961713Sgirish 303144961713Sgirish MUTEX_ENTER(nxgep->genlock); 303214ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 303344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 303444961713Sgirish "<== nxge_m_start: initialization failed")); 303544961713Sgirish MUTEX_EXIT(nxgep->genlock); 303644961713Sgirish return (EIO); 303744961713Sgirish } 303844961713Sgirish 303914ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 304014ea4bb7Ssd goto nxge_m_start_exit; 304144961713Sgirish /* 304244961713Sgirish * Start timer to check the system error and tx hangs 304344961713Sgirish */ 304444961713Sgirish nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state, 304544961713Sgirish NXGE_CHECK_TIMER); 304644961713Sgirish 3047a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3048a3c5bd6dSspeer 304944961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 305044961713Sgirish 305114ea4bb7Ssd nxge_m_start_exit: 305244961713Sgirish MUTEX_EXIT(nxgep->genlock); 305344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 305444961713Sgirish return (0); 305544961713Sgirish } 305644961713Sgirish 305744961713Sgirish /* 305844961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 305944961713Sgirish */ 306044961713Sgirish static void 306144961713Sgirish nxge_m_stop(void *arg) 306244961713Sgirish { 306344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 306444961713Sgirish 306544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 306644961713Sgirish 306744961713Sgirish if (nxgep->nxge_timerid) { 306844961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 306944961713Sgirish nxgep->nxge_timerid = 0; 307044961713Sgirish } 3071a3c5bd6dSspeer 3072a3c5bd6dSspeer MUTEX_ENTER(nxgep->genlock); 307344961713Sgirish nxge_uninit(nxgep); 307444961713Sgirish 307544961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 307644961713Sgirish 307744961713Sgirish MUTEX_EXIT(nxgep->genlock); 307844961713Sgirish 307944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 308044961713Sgirish } 308144961713Sgirish 308244961713Sgirish static int 308344961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr) 308444961713Sgirish { 308544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 308644961713Sgirish struct ether_addr addrp; 308744961713Sgirish 308844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst")); 308944961713Sgirish 309044961713Sgirish bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 309144961713Sgirish if (nxge_set_mac_addr(nxgep, &addrp)) { 309244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 309344961713Sgirish "<== nxge_m_unicst: set unitcast failed")); 309444961713Sgirish return (EINVAL); 309544961713Sgirish } 309644961713Sgirish 309744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst")); 309844961713Sgirish 309944961713Sgirish return (0); 310044961713Sgirish } 310144961713Sgirish 310244961713Sgirish static int 310344961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 310444961713Sgirish { 310544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 310644961713Sgirish struct ether_addr addrp; 310744961713Sgirish 310844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 310944961713Sgirish "==> nxge_m_multicst: add %d", add)); 311044961713Sgirish 311144961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 311244961713Sgirish if (add) { 311344961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 311444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 311544961713Sgirish "<== nxge_m_multicst: add multicast failed")); 311644961713Sgirish return (EINVAL); 311744961713Sgirish } 311844961713Sgirish } else { 311944961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 312044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 312144961713Sgirish "<== nxge_m_multicst: del multicast failed")); 312244961713Sgirish return (EINVAL); 312344961713Sgirish } 312444961713Sgirish } 312544961713Sgirish 312644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 312744961713Sgirish 312844961713Sgirish return (0); 312944961713Sgirish } 313044961713Sgirish 313144961713Sgirish static int 313244961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 313344961713Sgirish { 313444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 313544961713Sgirish 313644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 313744961713Sgirish "==> nxge_m_promisc: on %d", on)); 313844961713Sgirish 313944961713Sgirish if (nxge_set_promisc(nxgep, on)) { 314044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 314144961713Sgirish "<== nxge_m_promisc: set promisc failed")); 314244961713Sgirish return (EINVAL); 314344961713Sgirish } 314444961713Sgirish 314544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 314644961713Sgirish "<== nxge_m_promisc: on %d", on)); 314744961713Sgirish 314844961713Sgirish return (0); 314944961713Sgirish } 315044961713Sgirish 315144961713Sgirish static void 315244961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 315344961713Sgirish { 315444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 315556d930aeSspeer struct iocblk *iocp; 315644961713Sgirish boolean_t need_privilege; 315744961713Sgirish int err; 315844961713Sgirish int cmd; 315944961713Sgirish 316044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 316144961713Sgirish 316244961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 316344961713Sgirish iocp->ioc_error = 0; 316444961713Sgirish need_privilege = B_TRUE; 316544961713Sgirish cmd = iocp->ioc_cmd; 316644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 316744961713Sgirish switch (cmd) { 316844961713Sgirish default: 316944961713Sgirish miocnak(wq, mp, 0, EINVAL); 317044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 317144961713Sgirish return; 317244961713Sgirish 317344961713Sgirish case LB_GET_INFO_SIZE: 317444961713Sgirish case LB_GET_INFO: 317544961713Sgirish case LB_GET_MODE: 317644961713Sgirish need_privilege = B_FALSE; 317744961713Sgirish break; 317844961713Sgirish case LB_SET_MODE: 317944961713Sgirish break; 318044961713Sgirish 318144961713Sgirish case ND_GET: 318244961713Sgirish need_privilege = B_FALSE; 318344961713Sgirish break; 318444961713Sgirish case ND_SET: 318544961713Sgirish break; 318644961713Sgirish 318744961713Sgirish case NXGE_GET_MII: 318844961713Sgirish case NXGE_PUT_MII: 318944961713Sgirish case NXGE_GET64: 319044961713Sgirish case NXGE_PUT64: 319144961713Sgirish case NXGE_GET_TX_RING_SZ: 319244961713Sgirish case NXGE_GET_TX_DESC: 319344961713Sgirish case NXGE_TX_SIDE_RESET: 319444961713Sgirish case NXGE_RX_SIDE_RESET: 319544961713Sgirish case NXGE_GLOBAL_RESET: 319644961713Sgirish case NXGE_RESET_MAC: 319744961713Sgirish case NXGE_TX_REGS_DUMP: 319844961713Sgirish case NXGE_RX_REGS_DUMP: 319944961713Sgirish case NXGE_INT_REGS_DUMP: 320044961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 320144961713Sgirish case NXGE_PUT_TCAM: 320244961713Sgirish case NXGE_GET_TCAM: 320344961713Sgirish case NXGE_RTRACE: 320444961713Sgirish case NXGE_RDUMP: 320544961713Sgirish 320644961713Sgirish need_privilege = B_FALSE; 320744961713Sgirish break; 320844961713Sgirish case NXGE_INJECT_ERR: 320944961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 321044961713Sgirish nxge_err_inject(nxgep, wq, mp); 321144961713Sgirish break; 321244961713Sgirish } 321344961713Sgirish 321444961713Sgirish if (need_privilege) { 321556d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 321644961713Sgirish if (err != 0) { 321744961713Sgirish miocnak(wq, mp, 0, err); 321844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 321944961713Sgirish "<== nxge_m_ioctl: no priv")); 322044961713Sgirish return; 322144961713Sgirish } 322244961713Sgirish } 322344961713Sgirish 322444961713Sgirish switch (cmd) { 322544961713Sgirish case ND_GET: 322644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_GET command")); 322744961713Sgirish case ND_SET: 322844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_SET command")); 322944961713Sgirish nxge_param_ioctl(nxgep, wq, mp, iocp); 323044961713Sgirish break; 323144961713Sgirish 323244961713Sgirish case LB_GET_MODE: 323344961713Sgirish case LB_SET_MODE: 323444961713Sgirish case LB_GET_INFO_SIZE: 323544961713Sgirish case LB_GET_INFO: 323644961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 323744961713Sgirish break; 323844961713Sgirish 323944961713Sgirish case NXGE_GET_MII: 324044961713Sgirish case NXGE_PUT_MII: 324144961713Sgirish case NXGE_PUT_TCAM: 324244961713Sgirish case NXGE_GET_TCAM: 324344961713Sgirish case NXGE_GET64: 324444961713Sgirish case NXGE_PUT64: 324544961713Sgirish case NXGE_GET_TX_RING_SZ: 324644961713Sgirish case NXGE_GET_TX_DESC: 324744961713Sgirish case NXGE_TX_SIDE_RESET: 324844961713Sgirish case NXGE_RX_SIDE_RESET: 324944961713Sgirish case NXGE_GLOBAL_RESET: 325044961713Sgirish case NXGE_RESET_MAC: 325144961713Sgirish case NXGE_TX_REGS_DUMP: 325244961713Sgirish case NXGE_RX_REGS_DUMP: 325344961713Sgirish case NXGE_INT_REGS_DUMP: 325444961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 325544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 325644961713Sgirish "==> nxge_m_ioctl: cmd 0x%x", cmd)); 325744961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 325844961713Sgirish break; 325944961713Sgirish } 326044961713Sgirish 326144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 326244961713Sgirish } 326344961713Sgirish 326444961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 326544961713Sgirish 326644961713Sgirish static void 326744961713Sgirish nxge_m_resources(void *arg) 326844961713Sgirish { 326944961713Sgirish p_nxge_t nxgep = arg; 327044961713Sgirish mac_rx_fifo_t mrf; 327144961713Sgirish p_rx_rcr_rings_t rcr_rings; 327244961713Sgirish p_rx_rcr_ring_t *rcr_p; 327344961713Sgirish uint32_t i, ndmas; 327414ea4bb7Ssd nxge_status_t status; 327544961713Sgirish 327644961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources")); 327744961713Sgirish 327844961713Sgirish MUTEX_ENTER(nxgep->genlock); 327914ea4bb7Ssd 328014ea4bb7Ssd /* 328158324dfcSspeer * CR 6492541 Check to see if the drv_state has been initialized, 328214ea4bb7Ssd * if not * call nxge_init(). 328314ea4bb7Ssd */ 328414ea4bb7Ssd if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 328514ea4bb7Ssd status = nxge_init(nxgep); 328614ea4bb7Ssd if (status != NXGE_OK) 328714ea4bb7Ssd goto nxge_m_resources_exit; 328814ea4bb7Ssd } 328914ea4bb7Ssd 329044961713Sgirish mrf.mrf_type = MAC_RX_FIFO; 329144961713Sgirish mrf.mrf_blank = nxge_rx_hw_blank; 329244961713Sgirish mrf.mrf_arg = (void *)nxgep; 329344961713Sgirish 329444961713Sgirish mrf.mrf_normal_blank_time = 128; 329544961713Sgirish mrf.mrf_normal_pkt_count = 8; 329644961713Sgirish rcr_rings = nxgep->rx_rcr_rings; 329744961713Sgirish rcr_p = rcr_rings->rcr_rings; 329844961713Sgirish ndmas = rcr_rings->ndmas; 329944961713Sgirish 330014ea4bb7Ssd /* 330114ea4bb7Ssd * Export our receive resources to the MAC layer. 330214ea4bb7Ssd */ 330344961713Sgirish for (i = 0; i < ndmas; i++) { 330444961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle = 330544961713Sgirish mac_resource_add(nxgep->mach, 330644961713Sgirish (mac_resource_t *)&mrf); 330744961713Sgirish 330844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 330944961713Sgirish "==> nxge_m_resources: vdma %d dma %d " 331044961713Sgirish "rcrptr 0x%016llx mac_handle 0x%016llx", 331144961713Sgirish i, ((p_rx_rcr_ring_t)rcr_p[i])->rdc, 331244961713Sgirish rcr_p[i], 331344961713Sgirish ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle)); 331444961713Sgirish } 331544961713Sgirish 331614ea4bb7Ssd nxge_m_resources_exit: 331744961713Sgirish MUTEX_EXIT(nxgep->genlock); 331844961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources")); 331944961713Sgirish } 332044961713Sgirish 332158324dfcSspeer static void 332258324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory) 332358324dfcSspeer { 332458324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 332558324dfcSspeer int i; 332658324dfcSspeer nxge_mmac_t *mmac_info; 332758324dfcSspeer 332858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 332958324dfcSspeer 333058324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 333158324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 333258324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 333358324dfcSspeer 333458324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 333558324dfcSspeer if (factory) { 333658324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 333758324dfcSspeer = mmac_info->factory_mac_pool[slot][(ETHERADDRL-1) - i]; 333858324dfcSspeer } else { 333958324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 334058324dfcSspeer = mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i]; 334158324dfcSspeer } 334258324dfcSspeer } 334358324dfcSspeer } 334458324dfcSspeer 334558324dfcSspeer /* 334658324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 334758324dfcSspeer */ 334858324dfcSspeer static int 334958324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot) 335058324dfcSspeer { 335158324dfcSspeer uint8_t addrn; 335258324dfcSspeer uint8_t portn; 335358324dfcSspeer npi_mac_addr_t altmac; 33547b9fa28bSspeer hostinfo_t mac_rdc; 33557b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 335658324dfcSspeer 335758324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 335858324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 335958324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 336058324dfcSspeer 336158324dfcSspeer portn = nxgep->mac.portnum; 336258324dfcSspeer addrn = (uint8_t)slot - 1; 336358324dfcSspeer 336458324dfcSspeer if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn, 336558324dfcSspeer addrn, &altmac) != NPI_SUCCESS) 336658324dfcSspeer return (EIO); 33677b9fa28bSspeer 33687b9fa28bSspeer /* 33697b9fa28bSspeer * Set the rdc table number for the host info entry 33707b9fa28bSspeer * for this mac address slot. 33717b9fa28bSspeer */ 33727b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 33737b9fa28bSspeer mac_rdc.value = 0; 33747b9fa28bSspeer mac_rdc.bits.w0.rdc_tbl_num = clscfgp->mac_host_info[addrn].rdctbl; 33757b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 33767b9fa28bSspeer 33777b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 33787b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 33797b9fa28bSspeer return (EIO); 33807b9fa28bSspeer } 33817b9fa28bSspeer 338258324dfcSspeer /* 338358324dfcSspeer * Enable comparison with the alternate MAC address. 338458324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 338558324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 338658324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 338758324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 338858324dfcSspeer */ 338958324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 339058324dfcSspeer addrn = (uint8_t)slot - 1; 339158324dfcSspeer else 339258324dfcSspeer addrn = (uint8_t)slot; 339358324dfcSspeer 339458324dfcSspeer if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn) 339558324dfcSspeer != NPI_SUCCESS) 339658324dfcSspeer return (EIO); 339758324dfcSspeer 339858324dfcSspeer return (0); 339958324dfcSspeer } 340058324dfcSspeer 340158324dfcSspeer /* 340258324dfcSspeer * nxeg_m_mmac_add() - find an unused address slot, set the address 340358324dfcSspeer * value to the one specified, enable the port to start filtering on 340458324dfcSspeer * the new MAC address. Returns 0 on success. 340558324dfcSspeer */ 340658324dfcSspeer static int 340758324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 340858324dfcSspeer { 340958324dfcSspeer p_nxge_t nxgep = arg; 341058324dfcSspeer mac_addr_slot_t slot; 341158324dfcSspeer nxge_mmac_t *mmac_info; 341258324dfcSspeer int err; 341358324dfcSspeer nxge_status_t status; 341458324dfcSspeer 341558324dfcSspeer mutex_enter(nxgep->genlock); 341658324dfcSspeer 341758324dfcSspeer /* 341858324dfcSspeer * Make sure that nxge is initialized, if _start() has 341958324dfcSspeer * not been called. 342058324dfcSspeer */ 342158324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 342258324dfcSspeer status = nxge_init(nxgep); 342358324dfcSspeer if (status != NXGE_OK) { 342458324dfcSspeer mutex_exit(nxgep->genlock); 342558324dfcSspeer return (ENXIO); 342658324dfcSspeer } 342758324dfcSspeer } 342858324dfcSspeer 342958324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 343058324dfcSspeer if (mmac_info->naddrfree == 0) { 343158324dfcSspeer mutex_exit(nxgep->genlock); 343258324dfcSspeer return (ENOSPC); 343358324dfcSspeer } 343458324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 343558324dfcSspeer maddr->mma_addrlen)) { 343658324dfcSspeer mutex_exit(nxgep->genlock); 343758324dfcSspeer return (EINVAL); 343858324dfcSspeer } 343958324dfcSspeer /* 344058324dfcSspeer * Search for the first available slot. Because naddrfree 344158324dfcSspeer * is not zero, we are guaranteed to find one. 344258324dfcSspeer * Slot 0 is for unique (primary) MAC. The first alternate 344358324dfcSspeer * MAC slot is slot 1. 344458324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 344556d930aeSspeer * MAC slots but only the first 7 (or 15) slots have assigned factory 344658324dfcSspeer * MAC addresses. We first search among the slots without bundled 344758324dfcSspeer * factory MACs. If we fail to find one in that range, then we 344858324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 344958324dfcSspeer * will be wasted while the slot is used with a user MAC address. 345058324dfcSspeer * But the slot could be used by factory MAC again after calling 345158324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 345258324dfcSspeer */ 345358324dfcSspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 345458324dfcSspeer for (slot = mmac_info->num_factory_mmac + 1; 345558324dfcSspeer slot <= mmac_info->num_mmac; slot++) { 345658324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 345758324dfcSspeer break; 345858324dfcSspeer } 345958324dfcSspeer if (slot > mmac_info->num_mmac) { 346058324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 346158324dfcSspeer slot++) { 346258324dfcSspeer if (!(mmac_info->mac_pool[slot].flags 346358324dfcSspeer & MMAC_SLOT_USED)) 346458324dfcSspeer break; 346558324dfcSspeer } 346658324dfcSspeer } 346758324dfcSspeer } else { 346858324dfcSspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 346958324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 347058324dfcSspeer break; 347158324dfcSspeer } 347258324dfcSspeer } 347358324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 347458324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) { 347558324dfcSspeer mutex_exit(nxgep->genlock); 347658324dfcSspeer return (err); 347758324dfcSspeer } 347858324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 347958324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 348058324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 348158324dfcSspeer mmac_info->naddrfree--; 348258324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 348358324dfcSspeer 348458324dfcSspeer maddr->mma_slot = slot; 348558324dfcSspeer 348658324dfcSspeer mutex_exit(nxgep->genlock); 348758324dfcSspeer return (0); 348858324dfcSspeer } 348958324dfcSspeer 349058324dfcSspeer /* 349158324dfcSspeer * This function reserves an unused slot and programs the slot and the HW 349258324dfcSspeer * with a factory mac address. 349358324dfcSspeer */ 349458324dfcSspeer static int 349558324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr) 349658324dfcSspeer { 349758324dfcSspeer p_nxge_t nxgep = arg; 349858324dfcSspeer mac_addr_slot_t slot; 349958324dfcSspeer nxge_mmac_t *mmac_info; 350058324dfcSspeer int err; 350158324dfcSspeer nxge_status_t status; 350258324dfcSspeer 350358324dfcSspeer mutex_enter(nxgep->genlock); 350458324dfcSspeer 350558324dfcSspeer /* 350658324dfcSspeer * Make sure that nxge is initialized, if _start() has 350758324dfcSspeer * not been called. 350858324dfcSspeer */ 350958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 351058324dfcSspeer status = nxge_init(nxgep); 351158324dfcSspeer if (status != NXGE_OK) { 351258324dfcSspeer mutex_exit(nxgep->genlock); 351358324dfcSspeer return (ENXIO); 351458324dfcSspeer } 351558324dfcSspeer } 351658324dfcSspeer 351758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 351858324dfcSspeer if (mmac_info->naddrfree == 0) { 351958324dfcSspeer mutex_exit(nxgep->genlock); 352058324dfcSspeer return (ENOSPC); 352158324dfcSspeer } 352258324dfcSspeer 352358324dfcSspeer slot = maddr->mma_slot; 352458324dfcSspeer if (slot == -1) { /* -1: Take the first available slot */ 352558324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) { 352658324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 352758324dfcSspeer break; 352858324dfcSspeer } 352958324dfcSspeer if (slot > mmac_info->num_factory_mmac) { 353058324dfcSspeer mutex_exit(nxgep->genlock); 353158324dfcSspeer return (ENOSPC); 353258324dfcSspeer } 353358324dfcSspeer } 353458324dfcSspeer if (slot < 1 || slot > mmac_info->num_factory_mmac) { 353558324dfcSspeer /* 353658324dfcSspeer * Do not support factory MAC at a slot greater than 353758324dfcSspeer * num_factory_mmac even when there are available factory 353858324dfcSspeer * MAC addresses because the alternate MACs are bundled with 353958324dfcSspeer * slot[1] through slot[num_factory_mmac] 354058324dfcSspeer */ 354158324dfcSspeer mutex_exit(nxgep->genlock); 354258324dfcSspeer return (EINVAL); 354358324dfcSspeer } 354458324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 354558324dfcSspeer mutex_exit(nxgep->genlock); 354658324dfcSspeer return (EBUSY); 354758324dfcSspeer } 354858324dfcSspeer /* Verify the address to be reserved */ 354958324dfcSspeer if (!mac_unicst_verify(nxgep->mach, 355058324dfcSspeer mmac_info->factory_mac_pool[slot], ETHERADDRL)) { 355158324dfcSspeer mutex_exit(nxgep->genlock); 355258324dfcSspeer return (EINVAL); 355358324dfcSspeer } 355458324dfcSspeer if (err = nxge_altmac_set(nxgep, 355558324dfcSspeer mmac_info->factory_mac_pool[slot], slot)) { 355658324dfcSspeer mutex_exit(nxgep->genlock); 355758324dfcSspeer return (err); 355858324dfcSspeer } 355958324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL); 356058324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 356158324dfcSspeer mmac_info->naddrfree--; 356258324dfcSspeer 356358324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_TRUE); 356458324dfcSspeer mutex_exit(nxgep->genlock); 356558324dfcSspeer 356658324dfcSspeer /* Pass info back to the caller */ 356758324dfcSspeer maddr->mma_slot = slot; 356858324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 356958324dfcSspeer maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 357058324dfcSspeer 357158324dfcSspeer return (0); 357258324dfcSspeer } 357358324dfcSspeer 357458324dfcSspeer /* 357558324dfcSspeer * Remove the specified mac address and update the HW not to filter 357658324dfcSspeer * the mac address anymore. 357758324dfcSspeer */ 357858324dfcSspeer static int 357958324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 358058324dfcSspeer { 358158324dfcSspeer p_nxge_t nxgep = arg; 358258324dfcSspeer nxge_mmac_t *mmac_info; 358358324dfcSspeer uint8_t addrn; 358458324dfcSspeer uint8_t portn; 358558324dfcSspeer int err = 0; 358658324dfcSspeer nxge_status_t status; 358758324dfcSspeer 358858324dfcSspeer mutex_enter(nxgep->genlock); 358958324dfcSspeer 359058324dfcSspeer /* 359158324dfcSspeer * Make sure that nxge is initialized, if _start() has 359258324dfcSspeer * not been called. 359358324dfcSspeer */ 359458324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 359558324dfcSspeer status = nxge_init(nxgep); 359658324dfcSspeer if (status != NXGE_OK) { 359758324dfcSspeer mutex_exit(nxgep->genlock); 359858324dfcSspeer return (ENXIO); 359958324dfcSspeer } 360058324dfcSspeer } 360158324dfcSspeer 360258324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 360358324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 360458324dfcSspeer mutex_exit(nxgep->genlock); 360558324dfcSspeer return (EINVAL); 360658324dfcSspeer } 360758324dfcSspeer 360858324dfcSspeer portn = nxgep->mac.portnum; 360958324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 361058324dfcSspeer addrn = (uint8_t)slot - 1; 361158324dfcSspeer else 361258324dfcSspeer addrn = (uint8_t)slot; 361358324dfcSspeer 361458324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 361558324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 361658324dfcSspeer == NPI_SUCCESS) { 361758324dfcSspeer mmac_info->naddrfree++; 361858324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 361958324dfcSspeer /* 362058324dfcSspeer * Regardless if the MAC we just stopped filtering 362158324dfcSspeer * is a user addr or a facory addr, we must set 362258324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 362358324dfcSspeer * associated factory MAC to indicate that a factory 362458324dfcSspeer * MAC is available. 362558324dfcSspeer */ 362658324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 362758324dfcSspeer mmac_info->mac_pool[slot].flags 362858324dfcSspeer |= MMAC_VENDOR_ADDR; 362958324dfcSspeer } 363058324dfcSspeer /* 363158324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 363258324dfcSspeer * alternate MAC address if the slot is not used. 363358324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 363458324dfcSspeer * when the slot is not used!) 363558324dfcSspeer */ 363658324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 363758324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 363858324dfcSspeer } else { 363958324dfcSspeer err = EIO; 364058324dfcSspeer } 364158324dfcSspeer } else { 364258324dfcSspeer err = EINVAL; 364358324dfcSspeer } 364458324dfcSspeer 364558324dfcSspeer mutex_exit(nxgep->genlock); 364658324dfcSspeer return (err); 364758324dfcSspeer } 364858324dfcSspeer 364958324dfcSspeer 365058324dfcSspeer /* 365158324dfcSspeer * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve(). 365258324dfcSspeer */ 365358324dfcSspeer static int 365458324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 365558324dfcSspeer { 365658324dfcSspeer p_nxge_t nxgep = arg; 365758324dfcSspeer mac_addr_slot_t slot; 365858324dfcSspeer nxge_mmac_t *mmac_info; 365958324dfcSspeer int err = 0; 366058324dfcSspeer nxge_status_t status; 366158324dfcSspeer 366258324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 366358324dfcSspeer maddr->mma_addrlen)) 366458324dfcSspeer return (EINVAL); 366558324dfcSspeer 366658324dfcSspeer slot = maddr->mma_slot; 366758324dfcSspeer 366858324dfcSspeer mutex_enter(nxgep->genlock); 366958324dfcSspeer 367058324dfcSspeer /* 367158324dfcSspeer * Make sure that nxge is initialized, if _start() has 367258324dfcSspeer * not been called. 367358324dfcSspeer */ 367458324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 367558324dfcSspeer status = nxge_init(nxgep); 367658324dfcSspeer if (status != NXGE_OK) { 367758324dfcSspeer mutex_exit(nxgep->genlock); 367858324dfcSspeer return (ENXIO); 367958324dfcSspeer } 368058324dfcSspeer } 368158324dfcSspeer 368258324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 368358324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 368458324dfcSspeer mutex_exit(nxgep->genlock); 368558324dfcSspeer return (EINVAL); 368658324dfcSspeer } 368758324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 368858324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) 368958324dfcSspeer != 0) { 369058324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 369158324dfcSspeer ETHERADDRL); 369258324dfcSspeer /* 369358324dfcSspeer * Assume that the MAC passed down from the caller 369458324dfcSspeer * is not a factory MAC address (The user should 369558324dfcSspeer * call mmac_remove followed by mmac_reserve if 369658324dfcSspeer * he wants to use the factory MAC for this slot). 369758324dfcSspeer */ 369858324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 369958324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 370058324dfcSspeer } 370158324dfcSspeer } else { 370258324dfcSspeer err = EINVAL; 370358324dfcSspeer } 370458324dfcSspeer mutex_exit(nxgep->genlock); 370558324dfcSspeer return (err); 370658324dfcSspeer } 370758324dfcSspeer 370858324dfcSspeer /* 370958324dfcSspeer * nxge_m_mmac_get() - Get the MAC address and other information 371058324dfcSspeer * related to the slot. mma_flags should be set to 0 in the call. 371158324dfcSspeer * Note: although kstat shows MAC address as zero when a slot is 371258324dfcSspeer * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC 371358324dfcSspeer * to the caller as long as the slot is not using a user MAC address. 371458324dfcSspeer * The following table shows the rules, 371558324dfcSspeer * 371658324dfcSspeer * USED VENDOR mma_addr 371758324dfcSspeer * ------------------------------------------------------------ 371858324dfcSspeer * (1) Slot uses a user MAC: yes no user MAC 371958324dfcSspeer * (2) Slot uses a factory MAC: yes yes factory MAC 372058324dfcSspeer * (3) Slot is not used but is 372158324dfcSspeer * factory MAC capable: no yes factory MAC 372258324dfcSspeer * (4) Slot is not used and is 372358324dfcSspeer * not factory MAC capable: no no 0 372458324dfcSspeer * ------------------------------------------------------------ 372558324dfcSspeer */ 372658324dfcSspeer static int 372758324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 372858324dfcSspeer { 372958324dfcSspeer nxge_t *nxgep = arg; 373058324dfcSspeer mac_addr_slot_t slot; 373158324dfcSspeer nxge_mmac_t *mmac_info; 373258324dfcSspeer nxge_status_t status; 373358324dfcSspeer 373458324dfcSspeer slot = maddr->mma_slot; 373558324dfcSspeer 373658324dfcSspeer mutex_enter(nxgep->genlock); 373758324dfcSspeer 373858324dfcSspeer /* 373958324dfcSspeer * Make sure that nxge is initialized, if _start() has 374058324dfcSspeer * not been called. 374158324dfcSspeer */ 374258324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 374358324dfcSspeer status = nxge_init(nxgep); 374458324dfcSspeer if (status != NXGE_OK) { 374558324dfcSspeer mutex_exit(nxgep->genlock); 374658324dfcSspeer return (ENXIO); 374758324dfcSspeer } 374858324dfcSspeer } 374958324dfcSspeer 375058324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 375158324dfcSspeer 375258324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 375358324dfcSspeer mutex_exit(nxgep->genlock); 375458324dfcSspeer return (EINVAL); 375558324dfcSspeer } 375658324dfcSspeer maddr->mma_flags = 0; 375758324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) 375858324dfcSspeer maddr->mma_flags |= MMAC_SLOT_USED; 375958324dfcSspeer 376058324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) { 376158324dfcSspeer maddr->mma_flags |= MMAC_VENDOR_ADDR; 376258324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], 376358324dfcSspeer maddr->mma_addr, ETHERADDRL); 376458324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 376558324dfcSspeer } else { 376658324dfcSspeer if (maddr->mma_flags & MMAC_SLOT_USED) { 376758324dfcSspeer bcopy(mmac_info->mac_pool[slot].addr, 376858324dfcSspeer maddr->mma_addr, ETHERADDRL); 376958324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 377058324dfcSspeer } else { 377158324dfcSspeer bzero(maddr->mma_addr, ETHERADDRL); 377258324dfcSspeer maddr->mma_addrlen = 0; 377358324dfcSspeer } 377458324dfcSspeer } 377558324dfcSspeer mutex_exit(nxgep->genlock); 377658324dfcSspeer return (0); 377758324dfcSspeer } 377858324dfcSspeer 377958324dfcSspeer 378044961713Sgirish static boolean_t 378144961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 378244961713Sgirish { 378358324dfcSspeer nxge_t *nxgep = arg; 378458324dfcSspeer uint32_t *txflags = cap_data; 378558324dfcSspeer multiaddress_capab_t *mmacp = cap_data; 378644961713Sgirish 378758324dfcSspeer switch (cap) { 378858324dfcSspeer case MAC_CAPAB_HCKSUM: 378944961713Sgirish *txflags = HCKSUM_INET_PARTIAL; 379044961713Sgirish break; 379144961713Sgirish case MAC_CAPAB_POLL: 379244961713Sgirish /* 379344961713Sgirish * There's nothing for us to fill in, simply returning 379444961713Sgirish * B_TRUE stating that we support polling is sufficient. 379544961713Sgirish */ 379644961713Sgirish break; 379744961713Sgirish 379858324dfcSspeer case MAC_CAPAB_MULTIADDRESS: 379958324dfcSspeer mutex_enter(nxgep->genlock); 380058324dfcSspeer 380158324dfcSspeer mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac; 380258324dfcSspeer mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree; 380358324dfcSspeer mmacp->maddr_flag = 0; /* 0 is requried by PSARC2006/265 */ 380458324dfcSspeer /* 380558324dfcSspeer * maddr_handle is driver's private data, passed back to 380658324dfcSspeer * entry point functions as arg. 380758324dfcSspeer */ 380858324dfcSspeer mmacp->maddr_handle = nxgep; 380958324dfcSspeer mmacp->maddr_add = nxge_m_mmac_add; 381058324dfcSspeer mmacp->maddr_remove = nxge_m_mmac_remove; 381158324dfcSspeer mmacp->maddr_modify = nxge_m_mmac_modify; 381258324dfcSspeer mmacp->maddr_get = nxge_m_mmac_get; 381358324dfcSspeer mmacp->maddr_reserve = nxge_m_mmac_reserve; 381458324dfcSspeer 381558324dfcSspeer mutex_exit(nxgep->genlock); 381658324dfcSspeer break; 381730ac2e7bSml case MAC_CAPAB_LSO: { 381830ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 381930ac2e7bSml 38203d16f8e7Sml if (nxgep->soft_lso_enable) { 382130ac2e7bSml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 382230ac2e7bSml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 382330ac2e7bSml nxge_lso_max = NXGE_LSO_MAXLEN; 382430ac2e7bSml } 382530ac2e7bSml cap_lso->lso_basic_tcp_ipv4.lso_max = nxge_lso_max; 382630ac2e7bSml break; 382730ac2e7bSml } else { 382830ac2e7bSml return (B_FALSE); 382930ac2e7bSml } 383030ac2e7bSml } 383130ac2e7bSml 383244961713Sgirish default: 383344961713Sgirish return (B_FALSE); 383444961713Sgirish } 383544961713Sgirish return (B_TRUE); 383644961713Sgirish } 383744961713Sgirish 383844961713Sgirish /* 383944961713Sgirish * Module loading and removing entry points. 384044961713Sgirish */ 384144961713Sgirish 384244961713Sgirish static struct cb_ops nxge_cb_ops = { 384344961713Sgirish nodev, /* cb_open */ 384444961713Sgirish nodev, /* cb_close */ 384544961713Sgirish nodev, /* cb_strategy */ 384644961713Sgirish nodev, /* cb_print */ 384744961713Sgirish nodev, /* cb_dump */ 384844961713Sgirish nodev, /* cb_read */ 384944961713Sgirish nodev, /* cb_write */ 385044961713Sgirish nodev, /* cb_ioctl */ 385144961713Sgirish nodev, /* cb_devmap */ 385244961713Sgirish nodev, /* cb_mmap */ 385344961713Sgirish nodev, /* cb_segmap */ 385444961713Sgirish nochpoll, /* cb_chpoll */ 385544961713Sgirish ddi_prop_op, /* cb_prop_op */ 385644961713Sgirish NULL, 385744961713Sgirish D_MP, /* cb_flag */ 385844961713Sgirish CB_REV, /* rev */ 385944961713Sgirish nodev, /* int (*cb_aread)() */ 386044961713Sgirish nodev /* int (*cb_awrite)() */ 386144961713Sgirish }; 386244961713Sgirish 386344961713Sgirish static struct dev_ops nxge_dev_ops = { 386444961713Sgirish DEVO_REV, /* devo_rev */ 386544961713Sgirish 0, /* devo_refcnt */ 386644961713Sgirish nulldev, 386758324dfcSspeer nulldev, /* devo_identify */ 386858324dfcSspeer nulldev, /* devo_probe */ 386958324dfcSspeer nxge_attach, /* devo_attach */ 387058324dfcSspeer nxge_detach, /* devo_detach */ 387158324dfcSspeer nodev, /* devo_reset */ 387258324dfcSspeer &nxge_cb_ops, /* devo_cb_ops */ 387358324dfcSspeer (struct bus_ops *)NULL, /* devo_bus_ops */ 387458324dfcSspeer ddi_power /* devo_power */ 387544961713Sgirish }; 387644961713Sgirish 387744961713Sgirish extern struct mod_ops mod_driverops; 387844961713Sgirish 38792e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 388044961713Sgirish 388144961713Sgirish /* 388244961713Sgirish * Module linkage information for the kernel. 388344961713Sgirish */ 388444961713Sgirish static struct modldrv nxge_modldrv = { 388544961713Sgirish &mod_driverops, 388644961713Sgirish NXGE_DESC_VER, 388744961713Sgirish &nxge_dev_ops 388844961713Sgirish }; 388944961713Sgirish 389044961713Sgirish static struct modlinkage modlinkage = { 389144961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 389244961713Sgirish }; 389344961713Sgirish 389444961713Sgirish int 389544961713Sgirish _init(void) 389644961713Sgirish { 389744961713Sgirish int status; 389844961713Sgirish 389944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 390044961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 390144961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 390244961713Sgirish if (status != 0) { 390344961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 390444961713Sgirish "failed to init device soft state")); 390544961713Sgirish goto _init_exit; 390644961713Sgirish } 390744961713Sgirish status = mod_install(&modlinkage); 390844961713Sgirish if (status != 0) { 390944961713Sgirish ddi_soft_state_fini(&nxge_list); 391044961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 391144961713Sgirish goto _init_exit; 391244961713Sgirish } 391344961713Sgirish 391444961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 391544961713Sgirish 391644961713Sgirish _init_exit: 391744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 391844961713Sgirish 391944961713Sgirish return (status); 392044961713Sgirish } 392144961713Sgirish 392244961713Sgirish int 392344961713Sgirish _fini(void) 392444961713Sgirish { 392544961713Sgirish int status; 392644961713Sgirish 392744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 392844961713Sgirish 392944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 3930a3c5bd6dSspeer 3931a3c5bd6dSspeer if (nxge_mblks_pending) 3932a3c5bd6dSspeer return (EBUSY); 3933a3c5bd6dSspeer 393444961713Sgirish status = mod_remove(&modlinkage); 393544961713Sgirish if (status != DDI_SUCCESS) { 393644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 393744961713Sgirish "Module removal failed 0x%08x", 393844961713Sgirish status)); 393944961713Sgirish goto _fini_exit; 394044961713Sgirish } 394144961713Sgirish 394244961713Sgirish mac_fini_ops(&nxge_dev_ops); 394344961713Sgirish 394444961713Sgirish ddi_soft_state_fini(&nxge_list); 394544961713Sgirish 394644961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 394744961713Sgirish _fini_exit: 394844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 394944961713Sgirish 395044961713Sgirish return (status); 395144961713Sgirish } 395244961713Sgirish 395344961713Sgirish int 395444961713Sgirish _info(struct modinfo *modinfop) 395544961713Sgirish { 395644961713Sgirish int status; 395744961713Sgirish 395844961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 395944961713Sgirish status = mod_info(&modlinkage, modinfop); 396044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 396144961713Sgirish 396244961713Sgirish return (status); 396344961713Sgirish } 396444961713Sgirish 396544961713Sgirish /*ARGSUSED*/ 396644961713Sgirish static nxge_status_t 396744961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 396844961713Sgirish { 396944961713Sgirish 397044961713Sgirish int intr_types; 397144961713Sgirish int type = 0; 397244961713Sgirish int ddi_status = DDI_SUCCESS; 397344961713Sgirish nxge_status_t status = NXGE_OK; 397444961713Sgirish 397544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 397644961713Sgirish 397744961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 397844961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 397944961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 398044961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 398144961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 398244961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 398344961713Sgirish 398444961713Sgirish if (nxgep->niu_type == N2_NIU) { 398544961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 398644961713Sgirish } else if (nxge_msi_enable) { 398744961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 398844961713Sgirish } 398944961713Sgirish 399044961713Sgirish /* Get the supported interrupt types */ 399144961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 399244961713Sgirish != DDI_SUCCESS) { 399344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 399444961713Sgirish "ddi_intr_get_supported_types failed: status 0x%08x", 399544961713Sgirish ddi_status)); 399644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 399744961713Sgirish } 399844961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 399944961713Sgirish 400044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 400144961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 400244961713Sgirish 400344961713Sgirish /* 400444961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 400544961713Sgirish * nxge_msi_enable (1): 400644961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 400744961713Sgirish */ 400844961713Sgirish switch (nxge_msi_enable) { 400944961713Sgirish default: 401044961713Sgirish type = DDI_INTR_TYPE_FIXED; 401144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 401244961713Sgirish "use fixed (intx emulation) type %08x", 401344961713Sgirish type)); 401444961713Sgirish break; 401544961713Sgirish 401644961713Sgirish case 2: 401744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 401844961713Sgirish "ddi_intr_get_supported_types: 0x%08x", intr_types)); 401944961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 402044961713Sgirish type = DDI_INTR_TYPE_MSIX; 402144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 402244961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 402344961713Sgirish type)); 402444961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 402544961713Sgirish type = DDI_INTR_TYPE_MSI; 402644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 402744961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 402844961713Sgirish type)); 402944961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 403044961713Sgirish type = DDI_INTR_TYPE_FIXED; 403144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 403244961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 403344961713Sgirish type)); 403444961713Sgirish } 403544961713Sgirish break; 403644961713Sgirish 403744961713Sgirish case 1: 403844961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 403944961713Sgirish type = DDI_INTR_TYPE_MSI; 404044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 404144961713Sgirish "ddi_intr_get_supported_types: MSI 0x%08x", 404244961713Sgirish type)); 404344961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 404444961713Sgirish type = DDI_INTR_TYPE_MSIX; 404544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 404644961713Sgirish "ddi_intr_get_supported_types: MSIX 0x%08x", 404744961713Sgirish type)); 404844961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 404944961713Sgirish type = DDI_INTR_TYPE_FIXED; 405044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 405144961713Sgirish "ddi_intr_get_supported_types: MSXED0x%08x", 405244961713Sgirish type)); 405344961713Sgirish } 405444961713Sgirish } 405544961713Sgirish 405644961713Sgirish nxgep->nxge_intr_type.intr_type = type; 405744961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 405844961713Sgirish type == DDI_INTR_TYPE_FIXED) && 405944961713Sgirish nxgep->nxge_intr_type.niu_msi_enable) { 406044961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 406144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 406244961713Sgirish " nxge_add_intrs: " 406344961713Sgirish " nxge_add_intrs_adv failed: status 0x%08x", 406444961713Sgirish status)); 406544961713Sgirish return (status); 406644961713Sgirish } else { 406744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 406844961713Sgirish "interrupts registered : type %d", type)); 406944961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 407044961713Sgirish 407144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 407244961713Sgirish "\nAdded advanced nxge add_intr_adv " 407344961713Sgirish "intr type 0x%x\n", type)); 407444961713Sgirish 407544961713Sgirish return (status); 407644961713Sgirish } 407744961713Sgirish } 407844961713Sgirish 407944961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 408044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 408144961713Sgirish "failed to register interrupts")); 408244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 408344961713Sgirish } 408444961713Sgirish 408544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 408644961713Sgirish return (status); 408744961713Sgirish } 408844961713Sgirish 408944961713Sgirish /*ARGSUSED*/ 409044961713Sgirish static nxge_status_t 409144961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep) 409244961713Sgirish { 409344961713Sgirish 409444961713Sgirish int ddi_status = DDI_SUCCESS; 409544961713Sgirish nxge_status_t status = NXGE_OK; 409644961713Sgirish 409744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs")); 409844961713Sgirish 409944961713Sgirish nxgep->resched_id = NULL; 410044961713Sgirish nxgep->resched_running = B_FALSE; 410144961713Sgirish ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW, 410244961713Sgirish &nxgep->resched_id, 410344961713Sgirish NULL, NULL, nxge_reschedule, (caddr_t)nxgep); 410444961713Sgirish if (ddi_status != DDI_SUCCESS) { 410544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: " 410644961713Sgirish "ddi_add_softintrs failed: status 0x%08x", 410744961713Sgirish ddi_status)); 410844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 410944961713Sgirish } 411044961713Sgirish 411144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs")); 411244961713Sgirish 411344961713Sgirish return (status); 411444961713Sgirish } 411544961713Sgirish 411644961713Sgirish static nxge_status_t 411744961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 411844961713Sgirish { 411944961713Sgirish int intr_type; 412044961713Sgirish p_nxge_intr_t intrp; 412144961713Sgirish 412244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 412344961713Sgirish 412444961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 412544961713Sgirish intr_type = intrp->intr_type; 412644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 412744961713Sgirish intr_type)); 412844961713Sgirish 412944961713Sgirish switch (intr_type) { 413044961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 413144961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 413244961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 413344961713Sgirish 413444961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 413544961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 413644961713Sgirish 413744961713Sgirish default: 413844961713Sgirish return (NXGE_ERROR); 413944961713Sgirish } 414044961713Sgirish } 414144961713Sgirish 414244961713Sgirish 414344961713Sgirish /*ARGSUSED*/ 414444961713Sgirish static nxge_status_t 414544961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 414644961713Sgirish { 414744961713Sgirish dev_info_t *dip = nxgep->dip; 414844961713Sgirish p_nxge_ldg_t ldgp; 414944961713Sgirish p_nxge_intr_t intrp; 415044961713Sgirish uint_t *inthandler; 415144961713Sgirish void *arg1, *arg2; 415244961713Sgirish int behavior; 4153ec090658Sml int nintrs, navail, nrequest; 415444961713Sgirish int nactual, nrequired; 415544961713Sgirish int inum = 0; 415644961713Sgirish int x, y; 415744961713Sgirish int ddi_status = DDI_SUCCESS; 415844961713Sgirish nxge_status_t status = NXGE_OK; 415944961713Sgirish 416044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 416144961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 416244961713Sgirish intrp->start_inum = 0; 416344961713Sgirish 416444961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 416544961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 416644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 416744961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 416844961713Sgirish "nintrs: %d", ddi_status, nintrs)); 416944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 417044961713Sgirish } 417144961713Sgirish 417244961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 417344961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 417444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 417544961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 417644961713Sgirish "nintrs: %d", ddi_status, navail)); 417744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 417844961713Sgirish } 417944961713Sgirish 418044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 418144961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, navail %d", 418244961713Sgirish nintrs, navail)); 418344961713Sgirish 4184ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 4185ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 4186ec090658Sml nrequest = nxge_create_msi_property(nxgep); 4187ec090658Sml if (nrequest < navail) { 4188ec090658Sml navail = nrequest; 4189ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 4190ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 4191ec090658Sml "navail %d (nrequest %d)", 4192ec090658Sml nintrs, navail, nrequest)); 4193ec090658Sml } 4194ec090658Sml } 4195ec090658Sml 419644961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 419744961713Sgirish /* MSI must be power of 2 */ 419844961713Sgirish if ((navail & 16) == 16) { 419944961713Sgirish navail = 16; 420044961713Sgirish } else if ((navail & 8) == 8) { 420144961713Sgirish navail = 8; 420244961713Sgirish } else if ((navail & 4) == 4) { 420344961713Sgirish navail = 4; 420444961713Sgirish } else if ((navail & 2) == 2) { 420544961713Sgirish navail = 2; 420644961713Sgirish } else { 420744961713Sgirish navail = 1; 420844961713Sgirish } 420944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 421044961713Sgirish "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 421144961713Sgirish "navail %d", nintrs, navail)); 421244961713Sgirish } 421344961713Sgirish 421444961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 421544961713Sgirish DDI_INTR_ALLOC_NORMAL); 421644961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 421744961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 421844961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 421944961713Sgirish navail, &nactual, behavior); 422044961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 422144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 422244961713Sgirish " ddi_intr_alloc() failed: %d", 422344961713Sgirish ddi_status)); 422444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 422544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 422644961713Sgirish } 422744961713Sgirish 422844961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 422944961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 423044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 423144961713Sgirish " ddi_intr_get_pri() failed: %d", 423244961713Sgirish ddi_status)); 423344961713Sgirish /* Free already allocated interrupts */ 423444961713Sgirish for (y = 0; y < nactual; y++) { 423544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 423644961713Sgirish } 423744961713Sgirish 423844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 423944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 424044961713Sgirish } 424144961713Sgirish 424244961713Sgirish nrequired = 0; 424344961713Sgirish switch (nxgep->niu_type) { 424444961713Sgirish default: 424544961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 424644961713Sgirish break; 424744961713Sgirish 424844961713Sgirish case N2_NIU: 424944961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 425044961713Sgirish break; 425144961713Sgirish } 425244961713Sgirish 425344961713Sgirish if (status != NXGE_OK) { 425444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 425544961713Sgirish "nxge_add_intrs_adv_typ:nxge_ldgv_init " 425644961713Sgirish "failed: 0x%x", status)); 425744961713Sgirish /* Free already allocated interrupts */ 425844961713Sgirish for (y = 0; y < nactual; y++) { 425944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 426044961713Sgirish } 426144961713Sgirish 426244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 426344961713Sgirish return (status); 426444961713Sgirish } 426544961713Sgirish 426644961713Sgirish ldgp = nxgep->ldgvp->ldgp; 426744961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 426844961713Sgirish ldgp->vector = (uint8_t)x; 426944961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 427044961713Sgirish arg1 = ldgp->ldvp; 427144961713Sgirish arg2 = nxgep; 427244961713Sgirish if (ldgp->nldvs == 1) { 427344961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 427444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 427544961713Sgirish "nxge_add_intrs_adv_type: " 427644961713Sgirish "arg1 0x%x arg2 0x%x: " 427744961713Sgirish "1-1 int handler (entry %d intdata 0x%x)\n", 427844961713Sgirish arg1, arg2, 427944961713Sgirish x, ldgp->intdata)); 428044961713Sgirish } else if (ldgp->nldvs > 1) { 428144961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 428244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 428344961713Sgirish "nxge_add_intrs_adv_type: " 428444961713Sgirish "arg1 0x%x arg2 0x%x: " 428544961713Sgirish "nldevs %d int handler " 428644961713Sgirish "(entry %d intdata 0x%x)\n", 428744961713Sgirish arg1, arg2, 428844961713Sgirish ldgp->nldvs, x, ldgp->intdata)); 428944961713Sgirish } 429044961713Sgirish 429144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 429244961713Sgirish "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 429344961713Sgirish "htable 0x%llx", x, intrp->htable[x])); 429444961713Sgirish 429544961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 429644961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 429744961713Sgirish != DDI_SUCCESS) { 429844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 429944961713Sgirish "==> nxge_add_intrs_adv_type: failed #%d " 430044961713Sgirish "status 0x%x", x, ddi_status)); 430144961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 430244961713Sgirish (void) ddi_intr_remove_handler( 430344961713Sgirish intrp->htable[y]); 430444961713Sgirish } 430544961713Sgirish /* Free already allocated intr */ 430644961713Sgirish for (y = 0; y < nactual; y++) { 430744961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 430844961713Sgirish } 430944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 431044961713Sgirish 431144961713Sgirish (void) nxge_ldgv_uninit(nxgep); 431244961713Sgirish 431344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 431444961713Sgirish } 431544961713Sgirish intrp->intr_added++; 431644961713Sgirish } 431744961713Sgirish 431844961713Sgirish intrp->msi_intx_cnt = nactual; 431944961713Sgirish 432044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 432144961713Sgirish "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 432244961713Sgirish navail, nactual, 432344961713Sgirish intrp->msi_intx_cnt, 432444961713Sgirish intrp->intr_added)); 432544961713Sgirish 432644961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 432744961713Sgirish 432844961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 432944961713Sgirish 433044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 433144961713Sgirish 433244961713Sgirish return (status); 433344961713Sgirish } 433444961713Sgirish 433544961713Sgirish /*ARGSUSED*/ 433644961713Sgirish static nxge_status_t 433744961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 433844961713Sgirish { 433944961713Sgirish dev_info_t *dip = nxgep->dip; 434044961713Sgirish p_nxge_ldg_t ldgp; 434144961713Sgirish p_nxge_intr_t intrp; 434244961713Sgirish uint_t *inthandler; 434344961713Sgirish void *arg1, *arg2; 434444961713Sgirish int behavior; 434544961713Sgirish int nintrs, navail; 434644961713Sgirish int nactual, nrequired; 434744961713Sgirish int inum = 0; 434844961713Sgirish int x, y; 434944961713Sgirish int ddi_status = DDI_SUCCESS; 435044961713Sgirish nxge_status_t status = NXGE_OK; 435144961713Sgirish 435244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 435344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 435444961713Sgirish intrp->start_inum = 0; 435544961713Sgirish 435644961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 435744961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 435844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 435944961713Sgirish "ddi_intr_get_nintrs() failed, status: 0x%x%, " 436044961713Sgirish "nintrs: %d", status, nintrs)); 436144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 436244961713Sgirish } 436344961713Sgirish 436444961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 436544961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 436644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 436744961713Sgirish "ddi_intr_get_navail() failed, status: 0x%x%, " 436844961713Sgirish "nintrs: %d", ddi_status, navail)); 436944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 437044961713Sgirish } 437144961713Sgirish 437244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 437344961713Sgirish "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 437444961713Sgirish nintrs, navail)); 437544961713Sgirish 437644961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 437744961713Sgirish DDI_INTR_ALLOC_NORMAL); 437844961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 437944961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 438044961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 438144961713Sgirish navail, &nactual, behavior); 438244961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 438344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 438444961713Sgirish " ddi_intr_alloc() failed: %d", 438544961713Sgirish ddi_status)); 438644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 438744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 438844961713Sgirish } 438944961713Sgirish 439044961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 439144961713Sgirish (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 439244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 439344961713Sgirish " ddi_intr_get_pri() failed: %d", 439444961713Sgirish ddi_status)); 439544961713Sgirish /* Free already allocated interrupts */ 439644961713Sgirish for (y = 0; y < nactual; y++) { 439744961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 439844961713Sgirish } 439944961713Sgirish 440044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 440144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 440244961713Sgirish } 440344961713Sgirish 440444961713Sgirish nrequired = 0; 440544961713Sgirish switch (nxgep->niu_type) { 440644961713Sgirish default: 440744961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 440844961713Sgirish break; 440944961713Sgirish 441044961713Sgirish case N2_NIU: 441144961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 441244961713Sgirish break; 441344961713Sgirish } 441444961713Sgirish 441544961713Sgirish if (status != NXGE_OK) { 441644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 441744961713Sgirish "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 441844961713Sgirish "failed: 0x%x", status)); 441944961713Sgirish /* Free already allocated interrupts */ 442044961713Sgirish for (y = 0; y < nactual; y++) { 442144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 442244961713Sgirish } 442344961713Sgirish 442444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 442544961713Sgirish return (status); 442644961713Sgirish } 442744961713Sgirish 442844961713Sgirish ldgp = nxgep->ldgvp->ldgp; 442944961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 443044961713Sgirish ldgp->vector = (uint8_t)x; 443144961713Sgirish if (nxgep->niu_type != N2_NIU) { 443244961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 443344961713Sgirish } 443444961713Sgirish 443544961713Sgirish arg1 = ldgp->ldvp; 443644961713Sgirish arg2 = nxgep; 443744961713Sgirish if (ldgp->nldvs == 1) { 443844961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 443944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 444044961713Sgirish "nxge_add_intrs_adv_type_fix: " 444144961713Sgirish "1-1 int handler(%d) ldg %d ldv %d " 444244961713Sgirish "arg1 $%p arg2 $%p\n", 444344961713Sgirish x, ldgp->ldg, ldgp->ldvp->ldv, 444444961713Sgirish arg1, arg2)); 444544961713Sgirish } else if (ldgp->nldvs > 1) { 444644961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 444744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 444844961713Sgirish "nxge_add_intrs_adv_type_fix: " 444944961713Sgirish "shared ldv %d int handler(%d) ldv %d ldg %d" 445044961713Sgirish "arg1 0x%016llx arg2 0x%016llx\n", 445144961713Sgirish x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 445244961713Sgirish arg1, arg2)); 445344961713Sgirish } 445444961713Sgirish 445544961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 445644961713Sgirish (ddi_intr_handler_t *)inthandler, arg1, arg2)) 445744961713Sgirish != DDI_SUCCESS) { 445844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 445944961713Sgirish "==> nxge_add_intrs_adv_type_fix: failed #%d " 446044961713Sgirish "status 0x%x", x, ddi_status)); 446144961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 446244961713Sgirish (void) ddi_intr_remove_handler( 446344961713Sgirish intrp->htable[y]); 446444961713Sgirish } 446544961713Sgirish for (y = 0; y < nactual; y++) { 446644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 446744961713Sgirish } 446844961713Sgirish /* Free already allocated intr */ 446944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 447044961713Sgirish 447144961713Sgirish (void) nxge_ldgv_uninit(nxgep); 447244961713Sgirish 447344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 447444961713Sgirish } 447544961713Sgirish intrp->intr_added++; 447644961713Sgirish } 447744961713Sgirish 447844961713Sgirish intrp->msi_intx_cnt = nactual; 447944961713Sgirish 448044961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 448144961713Sgirish 448244961713Sgirish status = nxge_intr_ldgv_init(nxgep); 448344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 448444961713Sgirish 448544961713Sgirish return (status); 448644961713Sgirish } 448744961713Sgirish 448844961713Sgirish static void 448944961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 449044961713Sgirish { 449144961713Sgirish int i, inum; 449244961713Sgirish p_nxge_intr_t intrp; 449344961713Sgirish 449444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 449544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 449644961713Sgirish if (!intrp->intr_registered) { 449744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 449844961713Sgirish "<== nxge_remove_intrs: interrupts not registered")); 449944961713Sgirish return; 450044961713Sgirish } 450144961713Sgirish 450244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 450344961713Sgirish 450444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 450544961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 450644961713Sgirish intrp->intr_added); 450744961713Sgirish } else { 450844961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 450944961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 451044961713Sgirish } 451144961713Sgirish } 451244961713Sgirish 451344961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 451444961713Sgirish if (intrp->htable[inum]) { 451544961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 451644961713Sgirish } 451744961713Sgirish } 451844961713Sgirish 451944961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 452044961713Sgirish if (intrp->htable[inum]) { 452144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 452244961713Sgirish "nxge_remove_intrs: ddi_intr_free inum %d " 452344961713Sgirish "msi_intx_cnt %d intr_added %d", 452444961713Sgirish inum, 452544961713Sgirish intrp->msi_intx_cnt, 452644961713Sgirish intrp->intr_added)); 452744961713Sgirish 452844961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 452944961713Sgirish } 453044961713Sgirish } 453144961713Sgirish 453244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 453344961713Sgirish intrp->intr_registered = B_FALSE; 453444961713Sgirish intrp->intr_enabled = B_FALSE; 453544961713Sgirish intrp->msi_intx_cnt = 0; 453644961713Sgirish intrp->intr_added = 0; 453744961713Sgirish 4538a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 4539a3c5bd6dSspeer 4540ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 4541ec090658Sml "#msix-request"); 4542ec090658Sml 454344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 454444961713Sgirish } 454544961713Sgirish 454644961713Sgirish /*ARGSUSED*/ 454744961713Sgirish static void 454844961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep) 454944961713Sgirish { 455044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs")); 455144961713Sgirish if (nxgep->resched_id) { 455244961713Sgirish ddi_remove_softintr(nxgep->resched_id); 455344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 455444961713Sgirish "==> nxge_remove_soft_intrs: removed")); 455544961713Sgirish nxgep->resched_id = NULL; 455644961713Sgirish } 455744961713Sgirish 455844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs")); 455944961713Sgirish } 456044961713Sgirish 456144961713Sgirish /*ARGSUSED*/ 456244961713Sgirish static void 456344961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 456444961713Sgirish { 456544961713Sgirish p_nxge_intr_t intrp; 456644961713Sgirish int i; 456744961713Sgirish int status; 456844961713Sgirish 456944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 457044961713Sgirish 457144961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 457244961713Sgirish 457344961713Sgirish if (!intrp->intr_registered) { 457444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 457544961713Sgirish "interrupts are not registered")); 457644961713Sgirish return; 457744961713Sgirish } 457844961713Sgirish 457944961713Sgirish if (intrp->intr_enabled) { 458044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 458144961713Sgirish "<== nxge_intrs_enable: already enabled")); 458244961713Sgirish return; 458344961713Sgirish } 458444961713Sgirish 458544961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 458644961713Sgirish status = ddi_intr_block_enable(intrp->htable, 458744961713Sgirish intrp->intr_added); 458844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 458944961713Sgirish "block enable - status 0x%x total inums #%d\n", 459044961713Sgirish status, intrp->intr_added)); 459144961713Sgirish } else { 459244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 459344961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 459444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 459544961713Sgirish "ddi_intr_enable:enable - status 0x%x " 459644961713Sgirish "total inums %d enable inum #%d\n", 459744961713Sgirish status, intrp->intr_added, i)); 459844961713Sgirish if (status == DDI_SUCCESS) { 459944961713Sgirish intrp->intr_enabled = B_TRUE; 460044961713Sgirish } 460144961713Sgirish } 460244961713Sgirish } 460344961713Sgirish 460444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 460544961713Sgirish } 460644961713Sgirish 460744961713Sgirish /*ARGSUSED*/ 460844961713Sgirish static void 460944961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 461044961713Sgirish { 461144961713Sgirish p_nxge_intr_t intrp; 461244961713Sgirish int i; 461344961713Sgirish 461444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 461544961713Sgirish 461644961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 461744961713Sgirish 461844961713Sgirish if (!intrp->intr_registered) { 461944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 462044961713Sgirish "interrupts are not registered")); 462144961713Sgirish return; 462244961713Sgirish } 462344961713Sgirish 462444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 462544961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 462644961713Sgirish intrp->intr_added); 462744961713Sgirish } else { 462844961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 462944961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 463044961713Sgirish } 463144961713Sgirish } 463244961713Sgirish 463344961713Sgirish intrp->intr_enabled = B_FALSE; 463444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 463544961713Sgirish } 463644961713Sgirish 463744961713Sgirish static nxge_status_t 463844961713Sgirish nxge_mac_register(p_nxge_t nxgep) 463944961713Sgirish { 464044961713Sgirish mac_register_t *macp; 464144961713Sgirish int status; 464244961713Sgirish 464344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 464444961713Sgirish 464544961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 464644961713Sgirish return (NXGE_ERROR); 464744961713Sgirish 464844961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 464944961713Sgirish macp->m_driver = nxgep; 465044961713Sgirish macp->m_dip = nxgep->dip; 465144961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 465244961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 465344961713Sgirish macp->m_min_sdu = 0; 465444961713Sgirish macp->m_max_sdu = nxgep->mac.maxframesize - 465544961713Sgirish sizeof (struct ether_header) - ETHERFCSL - 4; 4656d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 465744961713Sgirish 465844961713Sgirish status = mac_register(macp, &nxgep->mach); 465944961713Sgirish mac_free(macp); 466044961713Sgirish 466144961713Sgirish if (status != 0) { 466244961713Sgirish cmn_err(CE_WARN, 466344961713Sgirish "!nxge_mac_register failed (status %d instance %d)", 466444961713Sgirish status, nxgep->instance); 466544961713Sgirish return (NXGE_ERROR); 466644961713Sgirish } 466744961713Sgirish 466844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 466944961713Sgirish "(instance %d)", nxgep->instance)); 467044961713Sgirish 467144961713Sgirish return (NXGE_OK); 467244961713Sgirish } 467344961713Sgirish 467444961713Sgirish void 467544961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 467644961713Sgirish { 467744961713Sgirish ssize_t size; 467844961713Sgirish mblk_t *nmp; 467944961713Sgirish uint8_t blk_id; 468044961713Sgirish uint8_t chan; 468144961713Sgirish uint32_t err_id; 468244961713Sgirish err_inject_t *eip; 468344961713Sgirish 468444961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 468544961713Sgirish 468644961713Sgirish size = 1024; 468744961713Sgirish nmp = mp->b_cont; 468844961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 468944961713Sgirish blk_id = eip->blk_id; 469044961713Sgirish err_id = eip->err_id; 469144961713Sgirish chan = eip->chan; 469244961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 469344961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 469444961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 469544961713Sgirish switch (blk_id) { 469644961713Sgirish case MAC_BLK_ID: 469744961713Sgirish break; 469844961713Sgirish case TXMAC_BLK_ID: 469944961713Sgirish break; 470044961713Sgirish case RXMAC_BLK_ID: 470144961713Sgirish break; 470244961713Sgirish case MIF_BLK_ID: 470344961713Sgirish break; 470444961713Sgirish case IPP_BLK_ID: 470544961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 470644961713Sgirish break; 470744961713Sgirish case TXC_BLK_ID: 470844961713Sgirish nxge_txc_inject_err(nxgep, err_id); 470944961713Sgirish break; 471044961713Sgirish case TXDMA_BLK_ID: 471144961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 471244961713Sgirish break; 471344961713Sgirish case RXDMA_BLK_ID: 471444961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 471544961713Sgirish break; 471644961713Sgirish case ZCP_BLK_ID: 471744961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 471844961713Sgirish break; 471944961713Sgirish case ESPC_BLK_ID: 472044961713Sgirish break; 472144961713Sgirish case FFLP_BLK_ID: 472244961713Sgirish break; 472344961713Sgirish case PHY_BLK_ID: 472444961713Sgirish break; 472544961713Sgirish case ETHER_SERDES_BLK_ID: 472644961713Sgirish break; 472744961713Sgirish case PCIE_SERDES_BLK_ID: 472844961713Sgirish break; 472944961713Sgirish case VIR_BLK_ID: 473044961713Sgirish break; 473144961713Sgirish } 473244961713Sgirish 473344961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 473444961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 473544961713Sgirish 473644961713Sgirish miocack(wq, mp, (int)size, 0); 473744961713Sgirish } 473844961713Sgirish 473944961713Sgirish static int 474044961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 474144961713Sgirish { 474244961713Sgirish p_nxge_hw_list_t hw_p; 474344961713Sgirish dev_info_t *p_dip; 474444961713Sgirish 474544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 474644961713Sgirish 474744961713Sgirish p_dip = nxgep->p_dip; 474844961713Sgirish MUTEX_ENTER(&nxge_common_lock); 474944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 475044961713Sgirish "==> nxge_init_common_dev:func # %d", 475144961713Sgirish nxgep->function_num)); 475244961713Sgirish /* 475344961713Sgirish * Loop through existing per neptune hardware list. 475444961713Sgirish */ 475544961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 475644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 475744961713Sgirish "==> nxge_init_common_device:func # %d " 475844961713Sgirish "hw_p $%p parent dip $%p", 475944961713Sgirish nxgep->function_num, 476044961713Sgirish hw_p, 476144961713Sgirish p_dip)); 476244961713Sgirish if (hw_p->parent_devp == p_dip) { 476344961713Sgirish nxgep->nxge_hw_p = hw_p; 476444961713Sgirish hw_p->ndevs++; 476544961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 476644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 476744961713Sgirish "==> nxge_init_common_device:func # %d " 476844961713Sgirish "hw_p $%p parent dip $%p " 476944961713Sgirish "ndevs %d (found)", 477044961713Sgirish nxgep->function_num, 477144961713Sgirish hw_p, 477244961713Sgirish p_dip, 477344961713Sgirish hw_p->ndevs)); 477444961713Sgirish break; 477544961713Sgirish } 477644961713Sgirish } 477744961713Sgirish 477844961713Sgirish if (hw_p == NULL) { 477944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 478044961713Sgirish "==> nxge_init_common_device:func # %d " 478144961713Sgirish "parent dip $%p (new)", 478244961713Sgirish nxgep->function_num, 478344961713Sgirish p_dip)); 478444961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 478544961713Sgirish hw_p->parent_devp = p_dip; 478644961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 478744961713Sgirish nxgep->nxge_hw_p = hw_p; 478844961713Sgirish hw_p->ndevs++; 478944961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 479044961713Sgirish hw_p->next = nxge_hw_list; 479159ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 479259ac0c16Sdavemq hw_p->niu_type = N2_NIU; 479359ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 479459ac0c16Sdavemq } else { 479559ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 47962e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 479759ac0c16Sdavemq } 479844961713Sgirish 479944961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 480044961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 480144961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 480244961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 480344961713Sgirish MUTEX_INIT(&hw_p->nxge_mii_lock, NULL, MUTEX_DRIVER, NULL); 480444961713Sgirish 480544961713Sgirish nxge_hw_list = hw_p; 480659ac0c16Sdavemq 480759ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 480844961713Sgirish } 480944961713Sgirish 481044961713Sgirish MUTEX_EXIT(&nxge_common_lock); 481159ac0c16Sdavemq 48122e59129aSraghus nxgep->platform_type = hw_p->platform_type; 481359ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 481459ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 481559ac0c16Sdavemq } 481659ac0c16Sdavemq 481744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 481844961713Sgirish "==> nxge_init_common_device (nxge_hw_list) $%p", 481944961713Sgirish nxge_hw_list)); 482044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 482144961713Sgirish 482244961713Sgirish return (NXGE_OK); 482344961713Sgirish } 482444961713Sgirish 482544961713Sgirish static void 482644961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 482744961713Sgirish { 482844961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 482944961713Sgirish dev_info_t *p_dip; 483044961713Sgirish 483144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 483244961713Sgirish if (nxgep->nxge_hw_p == NULL) { 483344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 483444961713Sgirish "<== nxge_uninit_common_device (no common)")); 483544961713Sgirish return; 483644961713Sgirish } 483744961713Sgirish 483844961713Sgirish MUTEX_ENTER(&nxge_common_lock); 483944961713Sgirish h_hw_p = nxge_hw_list; 484044961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 484144961713Sgirish p_dip = hw_p->parent_devp; 484244961713Sgirish if (nxgep->nxge_hw_p == hw_p && 484344961713Sgirish p_dip == nxgep->p_dip && 484444961713Sgirish nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 484544961713Sgirish hw_p->magic == NXGE_NEPTUNE_MAGIC) { 484644961713Sgirish 484744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 484844961713Sgirish "==> nxge_uninit_common_device:func # %d " 484944961713Sgirish "hw_p $%p parent dip $%p " 485044961713Sgirish "ndevs %d (found)", 485144961713Sgirish nxgep->function_num, 485244961713Sgirish hw_p, 485344961713Sgirish p_dip, 485444961713Sgirish hw_p->ndevs)); 485544961713Sgirish 485644961713Sgirish nxgep->nxge_hw_p = NULL; 485744961713Sgirish if (hw_p->ndevs) { 485844961713Sgirish hw_p->ndevs--; 485944961713Sgirish } 486044961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 486144961713Sgirish if (!hw_p->ndevs) { 486244961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 486344961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 486444961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 486544961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 486644961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mii_lock); 486744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 486844961713Sgirish "==> nxge_uninit_common_device: " 486944961713Sgirish "func # %d " 487044961713Sgirish "hw_p $%p parent dip $%p " 487144961713Sgirish "ndevs %d (last)", 487244961713Sgirish nxgep->function_num, 487344961713Sgirish hw_p, 487444961713Sgirish p_dip, 487544961713Sgirish hw_p->ndevs)); 487644961713Sgirish 487744961713Sgirish if (hw_p == nxge_hw_list) { 487844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 487944961713Sgirish "==> nxge_uninit_common_device:" 488044961713Sgirish "remove head func # %d " 488144961713Sgirish "hw_p $%p parent dip $%p " 488244961713Sgirish "ndevs %d (head)", 488344961713Sgirish nxgep->function_num, 488444961713Sgirish hw_p, 488544961713Sgirish p_dip, 488644961713Sgirish hw_p->ndevs)); 488744961713Sgirish nxge_hw_list = hw_p->next; 488844961713Sgirish } else { 488944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 489044961713Sgirish "==> nxge_uninit_common_device:" 489144961713Sgirish "remove middle func # %d " 489244961713Sgirish "hw_p $%p parent dip $%p " 489344961713Sgirish "ndevs %d (middle)", 489444961713Sgirish nxgep->function_num, 489544961713Sgirish hw_p, 489644961713Sgirish p_dip, 489744961713Sgirish hw_p->ndevs)); 489844961713Sgirish h_hw_p->next = hw_p->next; 489944961713Sgirish } 490044961713Sgirish 490144961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 490244961713Sgirish } 490344961713Sgirish break; 490444961713Sgirish } else { 490544961713Sgirish h_hw_p = hw_p; 490644961713Sgirish } 490744961713Sgirish } 490844961713Sgirish 490944961713Sgirish MUTEX_EXIT(&nxge_common_lock); 491044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 491144961713Sgirish "==> nxge_uninit_common_device (nxge_hw_list) $%p", 491244961713Sgirish nxge_hw_list)); 491344961713Sgirish 491444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 491544961713Sgirish } 491659ac0c16Sdavemq 491759ac0c16Sdavemq /* 49182e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 491959ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 492059ac0c16Sdavemq */ 492159ac0c16Sdavemq 492259ac0c16Sdavemq int 49232e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 492459ac0c16Sdavemq { 492559ac0c16Sdavemq int nports = 0; 492659ac0c16Sdavemq 49272e59129aSraghus switch (nxgep->niu_type) { 492859ac0c16Sdavemq case N2_NIU: 492959ac0c16Sdavemq case NEPTUNE_2_10GF: 493059ac0c16Sdavemq nports = 2; 493159ac0c16Sdavemq break; 493259ac0c16Sdavemq case NEPTUNE_4_1GC: 493359ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 493459ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 493559ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 493659ac0c16Sdavemq nports = 4; 493759ac0c16Sdavemq break; 493859ac0c16Sdavemq default: 49392e59129aSraghus switch (nxgep->platform_type) { 49402e59129aSraghus case P_NEPTUNE_NIU: 49412e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 49422e59129aSraghus nports = 2; 49432e59129aSraghus break; 49442e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 49452e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 49462e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 4947d81011f0Ssbehera case P_NEPTUNE_ALONSO: 49482e59129aSraghus nports = 4; 49492e59129aSraghus break; 49502e59129aSraghus default: 49512e59129aSraghus break; 49522e59129aSraghus } 495359ac0c16Sdavemq break; 495459ac0c16Sdavemq } 495559ac0c16Sdavemq 495659ac0c16Sdavemq return (nports); 495759ac0c16Sdavemq } 4958ec090658Sml 4959ec090658Sml /* 4960ec090658Sml * The following two functions are to support 4961ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 4962ec090658Sml */ 4963ec090658Sml static int 4964ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 4965ec090658Sml { 4966ec090658Sml int nmsi; 4967ec090658Sml extern int ncpus; 4968ec090658Sml 4969ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 4970ec090658Sml 4971ec090658Sml switch (nxgep->mac.portmode) { 4972ec090658Sml case PORT_10G_COPPER: 4973ec090658Sml case PORT_10G_FIBER: 4974ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 4975ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 4976ec090658Sml /* 4977ec090658Sml * The maximum MSI-X requested will be 8. 4978ec090658Sml * If the # of CPUs is less than 8, we will reqeust 4979ec090658Sml * # MSI-X based on the # of CPUs. 4980ec090658Sml */ 4981ec090658Sml if (ncpus >= NXGE_MSIX_REQUEST_10G) { 4982ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 4983ec090658Sml } else { 4984ec090658Sml nmsi = ncpus; 4985ec090658Sml } 4986ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 4987ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 4988ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 4989ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 4990ec090658Sml break; 4991ec090658Sml 4992ec090658Sml default: 4993ec090658Sml nmsi = NXGE_MSIX_REQUEST_1G; 4994ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 4995ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 4996ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 4997ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 4998ec090658Sml break; 4999ec090658Sml } 5000ec090658Sml 5001ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 5002ec090658Sml return (nmsi); 5003ec090658Sml } 5004