16349Sqs148142 /* 26349Sqs148142 * CDDL HEADER START 36349Sqs148142 * 46349Sqs148142 * The contents of this file are subject to the terms of the 56349Sqs148142 * Common Development and Distribution License (the "License"). 66349Sqs148142 * You may not use this file except in compliance with the License. 76349Sqs148142 * 86349Sqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96349Sqs148142 * or http://www.opensolaris.org/os/licensing. 106349Sqs148142 * See the License for the specific language governing permissions 116349Sqs148142 * and limitations under the License. 126349Sqs148142 * 136349Sqs148142 * When distributing Covered Code, include this CDDL HEADER in each 146349Sqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156349Sqs148142 * If applicable, add the following below this CDDL HEADER, with the 166349Sqs148142 * fields enclosed by brackets "[]" replaced with your own identifying 176349Sqs148142 * information: Portions Copyright [yyyy] [name of copyright owner] 186349Sqs148142 * 196349Sqs148142 * CDDL HEADER END 206349Sqs148142 */ 216349Sqs148142 /* 226349Sqs148142 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 236349Sqs148142 * Use is subject to license terms. 246349Sqs148142 */ 256349Sqs148142 266349Sqs148142 /* 276349Sqs148142 * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver. 286349Sqs148142 */ 296349Sqs148142 #include <hxge_impl.h> 306349Sqs148142 #include <hxge_pfc.h> 316349Sqs148142 326349Sqs148142 /* 336349Sqs148142 * PSARC/2007/453 MSI-X interrupt limit override 346349Sqs148142 * (This PSARC case is limited to MSI-X vectors 356349Sqs148142 * and SPARC platforms only). 366349Sqs148142 */ 376349Sqs148142 #if defined(_BIG_ENDIAN) 386349Sqs148142 uint32_t hxge_msi_enable = 2; 396349Sqs148142 #else 406349Sqs148142 uint32_t hxge_msi_enable = 1; 416349Sqs148142 #endif 426349Sqs148142 436349Sqs148142 /* 446349Sqs148142 * Globals: tunable parameters (/etc/system or adb) 456349Sqs148142 * 466349Sqs148142 */ 476349Sqs148142 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT; 486349Sqs148142 uint32_t hxge_rbr_spare_size = 0; 496349Sqs148142 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT; 506349Sqs148142 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT; 516349Sqs148142 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX; 526349Sqs148142 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN; 536349Sqs148142 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN; 547584SQiyan.Sun@Sun.COM uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE; 556349Sqs148142 566349Sqs148142 static hxge_os_mutex_t hxgedebuglock; 576349Sqs148142 static int hxge_debug_init = 0; 586349Sqs148142 596349Sqs148142 /* 606349Sqs148142 * Debugging flags: 616349Sqs148142 * hxge_no_tx_lb : transmit load balancing 626349Sqs148142 * hxge_tx_lb_policy: 0 - TCP/UDP port (default) 636349Sqs148142 * 1 - From the Stack 646349Sqs148142 * 2 - Destination IP Address 656349Sqs148142 */ 666349Sqs148142 uint32_t hxge_no_tx_lb = 0; 676349Sqs148142 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP; 686349Sqs148142 696349Sqs148142 /* 706349Sqs148142 * Add tunable to reduce the amount of time spent in the 716349Sqs148142 * ISR doing Rx Processing. 726349Sqs148142 */ 736349Sqs148142 uint32_t hxge_max_rx_pkts = 1024; 746349Sqs148142 756349Sqs148142 /* 766349Sqs148142 * Tunables to manage the receive buffer blocks. 776349Sqs148142 * 786349Sqs148142 * hxge_rx_threshold_hi: copy all buffers. 796349Sqs148142 * hxge_rx_bcopy_size_type: receive buffer block size type. 806349Sqs148142 * hxge_rx_threshold_lo: copy only up to tunable block size type. 816349Sqs148142 */ 826349Sqs148142 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6; 836349Sqs148142 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 846349Sqs148142 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_3; 856349Sqs148142 866349Sqs148142 rtrace_t hpi_rtracebuf; 876349Sqs148142 886349Sqs148142 /* 896349Sqs148142 * Function Prototypes 906349Sqs148142 */ 916349Sqs148142 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t); 926349Sqs148142 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t); 936349Sqs148142 static void hxge_unattach(p_hxge_t); 946349Sqs148142 956349Sqs148142 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t); 966349Sqs148142 976349Sqs148142 static hxge_status_t hxge_setup_mutexes(p_hxge_t); 986349Sqs148142 static void hxge_destroy_mutexes(p_hxge_t); 996349Sqs148142 1006349Sqs148142 static hxge_status_t hxge_map_regs(p_hxge_t hxgep); 1016349Sqs148142 static void hxge_unmap_regs(p_hxge_t hxgep); 1026349Sqs148142 1036349Sqs148142 hxge_status_t hxge_add_intrs(p_hxge_t hxgep); 1046349Sqs148142 static hxge_status_t hxge_add_soft_intrs(p_hxge_t hxgep); 1056349Sqs148142 static void hxge_remove_intrs(p_hxge_t hxgep); 1066349Sqs148142 static void hxge_remove_soft_intrs(p_hxge_t hxgep); 1076349Sqs148142 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep); 1086349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t); 1096349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t); 1106349Sqs148142 void hxge_intrs_enable(p_hxge_t hxgep); 1116349Sqs148142 static void hxge_intrs_disable(p_hxge_t hxgep); 1126349Sqs148142 static void hxge_suspend(p_hxge_t); 1136349Sqs148142 static hxge_status_t hxge_resume(p_hxge_t); 1146349Sqs148142 hxge_status_t hxge_setup_dev(p_hxge_t); 1156349Sqs148142 static void hxge_destroy_dev(p_hxge_t); 1166349Sqs148142 hxge_status_t hxge_alloc_mem_pool(p_hxge_t); 1176349Sqs148142 static void hxge_free_mem_pool(p_hxge_t); 1186349Sqs148142 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t); 1196349Sqs148142 static void hxge_free_rx_mem_pool(p_hxge_t); 1206349Sqs148142 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t); 1216349Sqs148142 static void hxge_free_tx_mem_pool(p_hxge_t); 1226349Sqs148142 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t, 1236349Sqs148142 struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t, 1246349Sqs148142 p_hxge_dma_common_t); 1256349Sqs148142 static void hxge_dma_mem_free(p_hxge_dma_common_t); 1266349Sqs148142 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t, 1276349Sqs148142 p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 1286349Sqs148142 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 1296349Sqs148142 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t, 1307618SMichael.Speer@Sun.COM p_hxge_dma_common_t *, struct ddi_dma_attr *, size_t); 1316349Sqs148142 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 1326349Sqs148142 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t, 1336349Sqs148142 p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 1346349Sqs148142 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 1356349Sqs148142 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t, 1366349Sqs148142 p_hxge_dma_common_t *, size_t); 1376349Sqs148142 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 1386349Sqs148142 static int hxge_init_common_dev(p_hxge_t); 1396349Sqs148142 static void hxge_uninit_common_dev(p_hxge_t); 1406349Sqs148142 1416349Sqs148142 /* 1426349Sqs148142 * The next declarations are for the GLDv3 interface. 1436349Sqs148142 */ 1446349Sqs148142 static int hxge_m_start(void *); 1456349Sqs148142 static void hxge_m_stop(void *); 1466349Sqs148142 static int hxge_m_unicst(void *, const uint8_t *); 1476349Sqs148142 static int hxge_m_multicst(void *, boolean_t, const uint8_t *); 1486349Sqs148142 static int hxge_m_promisc(void *, boolean_t); 1496349Sqs148142 static void hxge_m_ioctl(void *, queue_t *, mblk_t *); 1506349Sqs148142 static void hxge_m_resources(void *); 1516349Sqs148142 static hxge_status_t hxge_mac_register(p_hxge_t hxgep); 1526349Sqs148142 1536349Sqs148142 static int hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 1546349Sqs148142 static int hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 1556349Sqs148142 static int hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 1566349Sqs148142 static int hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 1576349Sqs148142 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *); 1587584SQiyan.Sun@Sun.COM static boolean_t hxge_param_locked(mac_prop_id_t pr_num); 1597584SQiyan.Sun@Sun.COM static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1607584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val); 1617584SQiyan.Sun@Sun.COM static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1627584SQiyan.Sun@Sun.COM uint_t pr_flags, uint_t pr_valsize, void *pr_val); 1637584SQiyan.Sun@Sun.COM static int hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num, 1647584SQiyan.Sun@Sun.COM uint_t pr_valsize, void *pr_val); 1657584SQiyan.Sun@Sun.COM static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, 1667584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val); 1677584SQiyan.Sun@Sun.COM static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, 1687584SQiyan.Sun@Sun.COM uint_t pr_flags, uint_t pr_valsize, void *pr_val); 1697584SQiyan.Sun@Sun.COM static void hxge_link_poll(void *arg); 1707584SQiyan.Sun@Sun.COM 1717584SQiyan.Sun@Sun.COM mac_priv_prop_t hxge_priv_props[] = { 1727584SQiyan.Sun@Sun.COM {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 1737584SQiyan.Sun@Sun.COM {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 1747584SQiyan.Sun@Sun.COM {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 1757584SQiyan.Sun@Sun.COM {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 1767584SQiyan.Sun@Sun.COM {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 1777584SQiyan.Sun@Sun.COM {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 1787584SQiyan.Sun@Sun.COM {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 1797584SQiyan.Sun@Sun.COM {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 1807584SQiyan.Sun@Sun.COM {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 1817584SQiyan.Sun@Sun.COM {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW} 1827584SQiyan.Sun@Sun.COM }; 1837584SQiyan.Sun@Sun.COM 1847584SQiyan.Sun@Sun.COM #define HXGE_MAX_PRIV_PROPS \ 1857584SQiyan.Sun@Sun.COM (sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t)) 1866349Sqs148142 1876349Sqs148142 #define HXGE_MAGIC 0x4E584745UL 1886349Sqs148142 #define MAX_DUMP_SZ 256 1896349Sqs148142 1907584SQiyan.Sun@Sun.COM #define HXGE_M_CALLBACK_FLAGS \ 1917584SQiyan.Sun@Sun.COM (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 1926349Sqs148142 1936349Sqs148142 extern mblk_t *hxge_m_tx(void *arg, mblk_t *mp); 1946349Sqs148142 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep); 1956349Sqs148142 1966349Sqs148142 static mac_callbacks_t hxge_m_callbacks = { 1976349Sqs148142 HXGE_M_CALLBACK_FLAGS, 1986349Sqs148142 hxge_m_stat, 1996349Sqs148142 hxge_m_start, 2006349Sqs148142 hxge_m_stop, 2016349Sqs148142 hxge_m_promisc, 2026349Sqs148142 hxge_m_multicst, 2036349Sqs148142 hxge_m_unicst, 2046349Sqs148142 hxge_m_tx, 2056349Sqs148142 hxge_m_resources, 2066349Sqs148142 hxge_m_ioctl, 2077584SQiyan.Sun@Sun.COM hxge_m_getcapab, 2087584SQiyan.Sun@Sun.COM NULL, 2097584SQiyan.Sun@Sun.COM NULL, 2107584SQiyan.Sun@Sun.COM hxge_m_setprop, 2117584SQiyan.Sun@Sun.COM hxge_m_getprop 2126349Sqs148142 }; 2136349Sqs148142 2146349Sqs148142 /* Enable debug messages as necessary. */ 2157584SQiyan.Sun@Sun.COM uint64_t hxge_debug_level = 0; 2166349Sqs148142 2176349Sqs148142 /* 2186349Sqs148142 * This list contains the instance structures for the Hydra 2196349Sqs148142 * devices present in the system. The lock exists to guarantee 2206349Sqs148142 * mutually exclusive access to the list. 2216349Sqs148142 */ 2226349Sqs148142 void *hxge_list = NULL; 2236349Sqs148142 void *hxge_hw_list = NULL; 2246349Sqs148142 hxge_os_mutex_t hxge_common_lock; 2256349Sqs148142 2266349Sqs148142 extern uint64_t hpi_debug_level; 2276349Sqs148142 2286349Sqs148142 extern hxge_status_t hxge_ldgv_init(); 2296349Sqs148142 extern hxge_status_t hxge_ldgv_uninit(); 2306349Sqs148142 extern hxge_status_t hxge_intr_ldgv_init(); 2316349Sqs148142 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr, 2326349Sqs148142 ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr); 2336349Sqs148142 extern void hxge_fm_fini(p_hxge_t hxgep); 2346349Sqs148142 2356349Sqs148142 /* 2366349Sqs148142 * Count used to maintain the number of buffers being used 2376349Sqs148142 * by Hydra instances and loaned up to the upper layers. 2386349Sqs148142 */ 2396349Sqs148142 uint32_t hxge_mblks_pending = 0; 2406349Sqs148142 2416349Sqs148142 /* 2426349Sqs148142 * Device register access attributes for PIO. 2436349Sqs148142 */ 2446349Sqs148142 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = { 2456349Sqs148142 DDI_DEVICE_ATTR_V0, 2466349Sqs148142 DDI_STRUCTURE_LE_ACC, 2476349Sqs148142 DDI_STRICTORDER_ACC, 2486349Sqs148142 }; 2496349Sqs148142 2506349Sqs148142 /* 2516349Sqs148142 * Device descriptor access attributes for DMA. 2526349Sqs148142 */ 2536349Sqs148142 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = { 2546349Sqs148142 DDI_DEVICE_ATTR_V0, 2556349Sqs148142 DDI_STRUCTURE_LE_ACC, 2566349Sqs148142 DDI_STRICTORDER_ACC 2576349Sqs148142 }; 2586349Sqs148142 2596349Sqs148142 /* 2606349Sqs148142 * Device buffer access attributes for DMA. 2616349Sqs148142 */ 2626349Sqs148142 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = { 2636349Sqs148142 DDI_DEVICE_ATTR_V0, 2646349Sqs148142 DDI_STRUCTURE_BE_ACC, 2656349Sqs148142 DDI_STRICTORDER_ACC 2666349Sqs148142 }; 2676349Sqs148142 2687618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rcr_desc_dma_attr = { 2697618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */ 2707618SMichael.Speer@Sun.COM 0, /* low address */ 2717618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */ 2727618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */ 2737618SMichael.Speer@Sun.COM 0x80000, /* alignment */ 2747618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */ 2757618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */ 2767618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */ 2777618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */ 2787618SMichael.Speer@Sun.COM 1, /* scatter/gather list length */ 2797618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */ 2807618SMichael.Speer@Sun.COM 0 /* attribute flags */ 2817618SMichael.Speer@Sun.COM }; 2827618SMichael.Speer@Sun.COM 2837618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_tx_desc_dma_attr = { 2846349Sqs148142 DMA_ATTR_V0, /* version number. */ 2856349Sqs148142 0, /* low address */ 2866349Sqs148142 0xffffffffffffffff, /* high address */ 2876349Sqs148142 0xffffffffffffffff, /* address counter max */ 2886349Sqs148142 0x100000, /* alignment */ 2896349Sqs148142 0xfc00fc, /* dlim_burstsizes */ 2906349Sqs148142 0x1, /* minimum transfer size */ 2916349Sqs148142 0xffffffffffffffff, /* maximum transfer size */ 2926349Sqs148142 0xffffffffffffffff, /* maximum segment size */ 2936349Sqs148142 1, /* scatter/gather list length */ 2946349Sqs148142 (unsigned int)1, /* granularity */ 2956349Sqs148142 0 /* attribute flags */ 2966349Sqs148142 }; 2976349Sqs148142 2987618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rbr_desc_dma_attr = { 2997618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */ 3007618SMichael.Speer@Sun.COM 0, /* low address */ 3017618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */ 3027618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */ 3037618SMichael.Speer@Sun.COM 0x40000, /* alignment */ 3047618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */ 3057618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */ 3067618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */ 3077618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */ 3087618SMichael.Speer@Sun.COM 1, /* scatter/gather list length */ 3097618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */ 3107618SMichael.Speer@Sun.COM 0 /* attribute flags */ 3117618SMichael.Speer@Sun.COM }; 3127618SMichael.Speer@Sun.COM 3137618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_mbox_dma_attr = { 3147618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */ 3157618SMichael.Speer@Sun.COM 0, /* low address */ 3167618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */ 3177618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */ 3187618SMichael.Speer@Sun.COM #if defined(_BIG_ENDIAN) 3197618SMichael.Speer@Sun.COM 0x2000, /* alignment */ 3207618SMichael.Speer@Sun.COM #else 3217618SMichael.Speer@Sun.COM 0x1000, /* alignment */ 3227618SMichael.Speer@Sun.COM #endif 3237618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */ 3247618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */ 3257618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */ 3267618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */ 3277618SMichael.Speer@Sun.COM 5, /* scatter/gather list length */ 3287618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */ 3297618SMichael.Speer@Sun.COM 0 /* attribute flags */ 3307618SMichael.Speer@Sun.COM }; 3317618SMichael.Speer@Sun.COM 3326349Sqs148142 ddi_dma_attr_t hxge_tx_dma_attr = { 3336349Sqs148142 DMA_ATTR_V0, /* version number. */ 3346349Sqs148142 0, /* low address */ 3356349Sqs148142 0xffffffffffffffff, /* high address */ 3366349Sqs148142 0xffffffffffffffff, /* address counter max */ 3376349Sqs148142 #if defined(_BIG_ENDIAN) 3386349Sqs148142 0x2000, /* alignment */ 3396349Sqs148142 #else 3406349Sqs148142 0x1000, /* alignment */ 3416349Sqs148142 #endif 3426349Sqs148142 0xfc00fc, /* dlim_burstsizes */ 3436349Sqs148142 0x1, /* minimum transfer size */ 3446349Sqs148142 0xffffffffffffffff, /* maximum transfer size */ 3456349Sqs148142 0xffffffffffffffff, /* maximum segment size */ 3466349Sqs148142 5, /* scatter/gather list length */ 3476349Sqs148142 (unsigned int)1, /* granularity */ 3486349Sqs148142 0 /* attribute flags */ 3496349Sqs148142 }; 3506349Sqs148142 3516349Sqs148142 ddi_dma_attr_t hxge_rx_dma_attr = { 3526349Sqs148142 DMA_ATTR_V0, /* version number. */ 3536349Sqs148142 0, /* low address */ 3546349Sqs148142 0xffffffffffffffff, /* high address */ 3556349Sqs148142 0xffffffffffffffff, /* address counter max */ 3566349Sqs148142 0x10000, /* alignment */ 3576349Sqs148142 0xfc00fc, /* dlim_burstsizes */ 3586349Sqs148142 0x1, /* minimum transfer size */ 3596349Sqs148142 0xffffffffffffffff, /* maximum transfer size */ 3606349Sqs148142 0xffffffffffffffff, /* maximum segment size */ 3616349Sqs148142 1, /* scatter/gather list length */ 3626349Sqs148142 (unsigned int)1, /* granularity */ 3636349Sqs148142 DDI_DMA_RELAXED_ORDERING /* attribute flags */ 3646349Sqs148142 }; 3656349Sqs148142 3666349Sqs148142 ddi_dma_lim_t hxge_dma_limits = { 3676349Sqs148142 (uint_t)0, /* dlim_addr_lo */ 3686349Sqs148142 (uint_t)0xffffffff, /* dlim_addr_hi */ 3696349Sqs148142 (uint_t)0xffffffff, /* dlim_cntr_max */ 3706349Sqs148142 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 3716349Sqs148142 0x1, /* dlim_minxfer */ 3726349Sqs148142 1024 /* dlim_speed */ 3736349Sqs148142 }; 3746349Sqs148142 3756349Sqs148142 dma_method_t hxge_force_dma = DVMA; 3766349Sqs148142 3776349Sqs148142 /* 3786349Sqs148142 * dma chunk sizes. 3796349Sqs148142 * 3806349Sqs148142 * Try to allocate the largest possible size 3816349Sqs148142 * so that fewer number of dma chunks would be managed 3826349Sqs148142 */ 3836349Sqs148142 size_t alloc_sizes[] = { 3846349Sqs148142 0x1000, 0x2000, 0x4000, 0x8000, 3856349Sqs148142 0x10000, 0x20000, 0x40000, 0x80000, 3866349Sqs148142 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000 3876349Sqs148142 }; 3886349Sqs148142 3896349Sqs148142 /* 3906349Sqs148142 * Translate "dev_t" to a pointer to the associated "dev_info_t". 3916349Sqs148142 */ 3926349Sqs148142 static int 3936349Sqs148142 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3946349Sqs148142 { 3956349Sqs148142 p_hxge_t hxgep = NULL; 3966349Sqs148142 int instance; 3976349Sqs148142 int status = DDI_SUCCESS; 3986349Sqs148142 3996349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach")); 4006349Sqs148142 4016349Sqs148142 /* 4026349Sqs148142 * Get the device instance since we'll need to setup or retrieve a soft 4036349Sqs148142 * state for this instance. 4046349Sqs148142 */ 4056349Sqs148142 instance = ddi_get_instance(dip); 4066349Sqs148142 4076349Sqs148142 switch (cmd) { 4086349Sqs148142 case DDI_ATTACH: 4096349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH")); 4106349Sqs148142 break; 4116349Sqs148142 4126349Sqs148142 case DDI_RESUME: 4136349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME")); 4146349Sqs148142 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 4156349Sqs148142 if (hxgep == NULL) { 4166349Sqs148142 status = DDI_FAILURE; 4176349Sqs148142 break; 4186349Sqs148142 } 4196349Sqs148142 if (hxgep->dip != dip) { 4206349Sqs148142 status = DDI_FAILURE; 4216349Sqs148142 break; 4226349Sqs148142 } 4236349Sqs148142 if (hxgep->suspended == DDI_PM_SUSPEND) { 4246349Sqs148142 status = ddi_dev_is_needed(hxgep->dip, 0, 1); 4256349Sqs148142 } else { 4266349Sqs148142 (void) hxge_resume(hxgep); 4276349Sqs148142 } 4286349Sqs148142 goto hxge_attach_exit; 4296349Sqs148142 4306349Sqs148142 case DDI_PM_RESUME: 4316349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME")); 4326349Sqs148142 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 4336349Sqs148142 if (hxgep == NULL) { 4346349Sqs148142 status = DDI_FAILURE; 4356349Sqs148142 break; 4366349Sqs148142 } 4376349Sqs148142 if (hxgep->dip != dip) { 4386349Sqs148142 status = DDI_FAILURE; 4396349Sqs148142 break; 4406349Sqs148142 } 4416349Sqs148142 (void) hxge_resume(hxgep); 4426349Sqs148142 goto hxge_attach_exit; 4436349Sqs148142 4446349Sqs148142 default: 4456349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown")); 4466349Sqs148142 status = DDI_FAILURE; 4476349Sqs148142 goto hxge_attach_exit; 4486349Sqs148142 } 4496349Sqs148142 4506349Sqs148142 if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) { 4516349Sqs148142 status = DDI_FAILURE; 4526349Sqs148142 HXGE_ERROR_MSG((hxgep, DDI_CTL, 4536349Sqs148142 "ddi_soft_state_zalloc failed")); 4546349Sqs148142 goto hxge_attach_exit; 4556349Sqs148142 } 4566349Sqs148142 4576349Sqs148142 hxgep = ddi_get_soft_state(hxge_list, instance); 4586349Sqs148142 if (hxgep == NULL) { 4596349Sqs148142 status = HXGE_ERROR; 4606349Sqs148142 HXGE_ERROR_MSG((hxgep, DDI_CTL, 4616349Sqs148142 "ddi_get_soft_state failed")); 4626349Sqs148142 goto hxge_attach_fail2; 4636349Sqs148142 } 4646349Sqs148142 4656349Sqs148142 hxgep->drv_state = 0; 4666349Sqs148142 hxgep->dip = dip; 4676349Sqs148142 hxgep->instance = instance; 4686349Sqs148142 hxgep->p_dip = ddi_get_parent(dip); 4696349Sqs148142 hxgep->hxge_debug_level = hxge_debug_level; 4706349Sqs148142 hpi_debug_level = hxge_debug_level; 4716349Sqs148142 4726349Sqs148142 hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr, 4736349Sqs148142 &hxge_rx_dma_attr); 4746349Sqs148142 4756349Sqs148142 status = hxge_map_regs(hxgep); 4766349Sqs148142 if (status != HXGE_OK) { 4776349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed")); 4786349Sqs148142 goto hxge_attach_fail3; 4796349Sqs148142 } 4806349Sqs148142 4816349Sqs148142 status = hxge_init_common_dev(hxgep); 4826349Sqs148142 if (status != HXGE_OK) { 4836349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4846349Sqs148142 "hxge_init_common_dev failed")); 4856349Sqs148142 goto hxge_attach_fail4; 4866349Sqs148142 } 4876349Sqs148142 4886349Sqs148142 /* 4896349Sqs148142 * Setup the Ndd parameters for this instance. 4906349Sqs148142 */ 4916349Sqs148142 hxge_init_param(hxgep); 4926349Sqs148142 4936349Sqs148142 /* 4946349Sqs148142 * Setup Register Tracing Buffer. 4956349Sqs148142 */ 4966349Sqs148142 hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf); 4976349Sqs148142 4986349Sqs148142 /* init stats ptr */ 4996349Sqs148142 hxge_init_statsp(hxgep); 5006349Sqs148142 5017584SQiyan.Sun@Sun.COM status = hxge_setup_mutexes(hxgep); 5027584SQiyan.Sun@Sun.COM if (status != HXGE_OK) { 5037584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed")); 5047584SQiyan.Sun@Sun.COM goto hxge_attach_fail; 5057584SQiyan.Sun@Sun.COM } 5067584SQiyan.Sun@Sun.COM 5076349Sqs148142 status = hxge_get_config_properties(hxgep); 5086349Sqs148142 if (status != HXGE_OK) { 5096349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed")); 5106349Sqs148142 goto hxge_attach_fail; 5116349Sqs148142 } 5126349Sqs148142 5136349Sqs148142 /* 5146349Sqs148142 * Setup the Kstats for the driver. 5156349Sqs148142 */ 5166349Sqs148142 hxge_setup_kstats(hxgep); 5176349Sqs148142 hxge_setup_param(hxgep); 5186349Sqs148142 5196349Sqs148142 status = hxge_setup_system_dma_pages(hxgep); 5206349Sqs148142 if (status != HXGE_OK) { 5216349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed")); 5226349Sqs148142 goto hxge_attach_fail; 5236349Sqs148142 } 5246349Sqs148142 5256349Sqs148142 hxge_hw_id_init(hxgep); 5266349Sqs148142 hxge_hw_init_niu_common(hxgep); 5276349Sqs148142 5286349Sqs148142 status = hxge_setup_dev(hxgep); 5296349Sqs148142 if (status != DDI_SUCCESS) { 5306349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed")); 5316349Sqs148142 goto hxge_attach_fail; 5326349Sqs148142 } 5336349Sqs148142 5346349Sqs148142 status = hxge_add_intrs(hxgep); 5356349Sqs148142 if (status != DDI_SUCCESS) { 5366349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed")); 5376349Sqs148142 goto hxge_attach_fail; 5386349Sqs148142 } 5396349Sqs148142 5406349Sqs148142 status = hxge_add_soft_intrs(hxgep); 5416349Sqs148142 if (status != DDI_SUCCESS) { 5426349Sqs148142 HXGE_DEBUG_MSG((hxgep, HXGE_ERR_CTL, "add_soft_intr failed")); 5436349Sqs148142 goto hxge_attach_fail; 5446349Sqs148142 } 5456349Sqs148142 5466349Sqs148142 /* 5476349Sqs148142 * Enable interrupts. 5486349Sqs148142 */ 5496349Sqs148142 hxge_intrs_enable(hxgep); 5506349Sqs148142 5516349Sqs148142 if ((status = hxge_mac_register(hxgep)) != HXGE_OK) { 5526349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 5536349Sqs148142 "unable to register to mac layer (%d)", status)); 5546349Sqs148142 goto hxge_attach_fail; 5556349Sqs148142 } 5567584SQiyan.Sun@Sun.COM mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN); 5577584SQiyan.Sun@Sun.COM hxgep->timeout.link_status = 0; 5587584SQiyan.Sun@Sun.COM hxgep->timeout.ticks = drv_usectohz(2 * 1000000); 5597584SQiyan.Sun@Sun.COM 5607584SQiyan.Sun@Sun.COM /* Start the link status timer to check the link status */ 5617584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock); 5627584SQiyan.Sun@Sun.COM hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 5637584SQiyan.Sun@Sun.COM hxgep->timeout.ticks); 5647584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock); 5656349Sqs148142 5666349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)", 5676349Sqs148142 instance)); 5686349Sqs148142 5696349Sqs148142 goto hxge_attach_exit; 5706349Sqs148142 5716349Sqs148142 hxge_attach_fail: 5726349Sqs148142 hxge_unattach(hxgep); 5736349Sqs148142 goto hxge_attach_fail1; 5746349Sqs148142 5756349Sqs148142 hxge_attach_fail5: 5766349Sqs148142 /* 5776349Sqs148142 * Tear down the ndd parameters setup. 5786349Sqs148142 */ 5796349Sqs148142 hxge_destroy_param(hxgep); 5806349Sqs148142 5816349Sqs148142 /* 5826349Sqs148142 * Tear down the kstat setup. 5836349Sqs148142 */ 5846349Sqs148142 hxge_destroy_kstats(hxgep); 5856349Sqs148142 5866349Sqs148142 hxge_attach_fail4: 5876349Sqs148142 if (hxgep->hxge_hw_p) { 5886349Sqs148142 hxge_uninit_common_dev(hxgep); 5896349Sqs148142 hxgep->hxge_hw_p = NULL; 5906349Sqs148142 } 5916349Sqs148142 hxge_attach_fail3: 5926349Sqs148142 /* 5936349Sqs148142 * Unmap the register setup. 5946349Sqs148142 */ 5956349Sqs148142 hxge_unmap_regs(hxgep); 5966349Sqs148142 5976349Sqs148142 hxge_fm_fini(hxgep); 5986349Sqs148142 5996349Sqs148142 hxge_attach_fail2: 6006349Sqs148142 ddi_soft_state_free(hxge_list, hxgep->instance); 6016349Sqs148142 6026349Sqs148142 hxge_attach_fail1: 6036349Sqs148142 if (status != HXGE_OK) 6046349Sqs148142 status = (HXGE_ERROR | HXGE_DDI_FAILED); 6056349Sqs148142 hxgep = NULL; 6066349Sqs148142 6076349Sqs148142 hxge_attach_exit: 6086349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x", 6096349Sqs148142 status)); 6106349Sqs148142 6116349Sqs148142 return (status); 6126349Sqs148142 } 6136349Sqs148142 6146349Sqs148142 static int 6156349Sqs148142 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 6166349Sqs148142 { 6176349Sqs148142 int status = DDI_SUCCESS; 6186349Sqs148142 int instance; 6196349Sqs148142 p_hxge_t hxgep = NULL; 6206349Sqs148142 6216349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach")); 6226349Sqs148142 instance = ddi_get_instance(dip); 6236349Sqs148142 hxgep = ddi_get_soft_state(hxge_list, instance); 6246349Sqs148142 if (hxgep == NULL) { 6256349Sqs148142 status = DDI_FAILURE; 6266349Sqs148142 goto hxge_detach_exit; 6276349Sqs148142 } 6286349Sqs148142 6296349Sqs148142 switch (cmd) { 6306349Sqs148142 case DDI_DETACH: 6316349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH")); 6326349Sqs148142 break; 6336349Sqs148142 6346349Sqs148142 case DDI_PM_SUSPEND: 6356349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 6366349Sqs148142 hxgep->suspended = DDI_PM_SUSPEND; 6376349Sqs148142 hxge_suspend(hxgep); 6386349Sqs148142 break; 6396349Sqs148142 6406349Sqs148142 case DDI_SUSPEND: 6416349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND")); 6426349Sqs148142 if (hxgep->suspended != DDI_PM_SUSPEND) { 6436349Sqs148142 hxgep->suspended = DDI_SUSPEND; 6446349Sqs148142 hxge_suspend(hxgep); 6456349Sqs148142 } 6466349Sqs148142 break; 6476349Sqs148142 6486349Sqs148142 default: 6496349Sqs148142 status = DDI_FAILURE; 6506349Sqs148142 break; 6516349Sqs148142 } 6526349Sqs148142 6536349Sqs148142 if (cmd != DDI_DETACH) 6546349Sqs148142 goto hxge_detach_exit; 6556349Sqs148142 6566349Sqs148142 /* 6576349Sqs148142 * Stop the xcvr polling. 6586349Sqs148142 */ 6596349Sqs148142 hxgep->suspended = cmd; 6606349Sqs148142 6617584SQiyan.Sun@Sun.COM /* Stop the link status timer before unregistering */ 6627584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock); 6637584SQiyan.Sun@Sun.COM if (hxgep->timeout.id) 6647584SQiyan.Sun@Sun.COM (void) untimeout(hxgep->timeout.id); 6657584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock); 6667584SQiyan.Sun@Sun.COM 6676349Sqs148142 if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) { 6686349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6696349Sqs148142 "<== hxge_detach status = 0x%08X", status)); 6706349Sqs148142 return (DDI_FAILURE); 6716349Sqs148142 } 6726349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 6736349Sqs148142 "<== hxge_detach (mac_unregister) status = 0x%08X", status)); 6746349Sqs148142 6756349Sqs148142 hxge_unattach(hxgep); 6766349Sqs148142 hxgep = NULL; 6776349Sqs148142 6786349Sqs148142 hxge_detach_exit: 6796349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X", 6806349Sqs148142 status)); 6816349Sqs148142 6826349Sqs148142 return (status); 6836349Sqs148142 } 6846349Sqs148142 6856349Sqs148142 static void 6866349Sqs148142 hxge_unattach(p_hxge_t hxgep) 6876349Sqs148142 { 6886349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach")); 6896349Sqs148142 6906349Sqs148142 if (hxgep == NULL || hxgep->dev_regs == NULL) { 6916349Sqs148142 return; 6926349Sqs148142 } 6936349Sqs148142 6946349Sqs148142 if (hxgep->hxge_hw_p) { 6956349Sqs148142 hxge_uninit_common_dev(hxgep); 6966349Sqs148142 hxgep->hxge_hw_p = NULL; 6976349Sqs148142 } 6986349Sqs148142 6996349Sqs148142 if (hxgep->hxge_timerid) { 7006349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 7016349Sqs148142 hxgep->hxge_timerid = 0; 7026349Sqs148142 } 7036349Sqs148142 7046349Sqs148142 /* Stop any further interrupts. */ 7056349Sqs148142 hxge_remove_intrs(hxgep); 7066349Sqs148142 7076349Sqs148142 /* Remove soft interrups */ 7086349Sqs148142 hxge_remove_soft_intrs(hxgep); 7096349Sqs148142 7106349Sqs148142 /* Stop the device and free resources. */ 7116349Sqs148142 hxge_destroy_dev(hxgep); 7126349Sqs148142 7136349Sqs148142 /* Tear down the ndd parameters setup. */ 7146349Sqs148142 hxge_destroy_param(hxgep); 7156349Sqs148142 7166349Sqs148142 /* Tear down the kstat setup. */ 7176349Sqs148142 hxge_destroy_kstats(hxgep); 7186349Sqs148142 7196349Sqs148142 /* 7206349Sqs148142 * Remove the list of ndd parameters which were setup during attach. 7216349Sqs148142 */ 7226349Sqs148142 if (hxgep->dip) { 7236349Sqs148142 HXGE_DEBUG_MSG((hxgep, OBP_CTL, 7246349Sqs148142 " hxge_unattach: remove all properties")); 7256349Sqs148142 (void) ddi_prop_remove_all(hxgep->dip); 7266349Sqs148142 } 7276349Sqs148142 7286349Sqs148142 /* 7296864Sqs148142 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any 7306864Sqs148142 * previous state before unmapping the registers. 7316864Sqs148142 */ 7326864Sqs148142 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E); 7336864Sqs148142 HXGE_DELAY(1000); 7346864Sqs148142 7356864Sqs148142 /* 7366349Sqs148142 * Unmap the register setup. 7376349Sqs148142 */ 7386349Sqs148142 hxge_unmap_regs(hxgep); 7396349Sqs148142 7406349Sqs148142 hxge_fm_fini(hxgep); 7416349Sqs148142 7427584SQiyan.Sun@Sun.COM /* Destroy all mutexes. */ 7437584SQiyan.Sun@Sun.COM hxge_destroy_mutexes(hxgep); 7447584SQiyan.Sun@Sun.COM 7456349Sqs148142 /* 7466349Sqs148142 * Free the soft state data structures allocated with this instance. 7476349Sqs148142 */ 7486349Sqs148142 ddi_soft_state_free(hxge_list, hxgep->instance); 7496349Sqs148142 7506349Sqs148142 HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach")); 7516349Sqs148142 } 7526349Sqs148142 7536349Sqs148142 static hxge_status_t 7546349Sqs148142 hxge_map_regs(p_hxge_t hxgep) 7556349Sqs148142 { 7566349Sqs148142 int ddi_status = DDI_SUCCESS; 7576349Sqs148142 p_dev_regs_t dev_regs; 7586349Sqs148142 7596349Sqs148142 #ifdef HXGE_DEBUG 7606349Sqs148142 char *sysname; 7616349Sqs148142 #endif 7626349Sqs148142 7636349Sqs148142 off_t regsize; 7646349Sqs148142 hxge_status_t status = HXGE_OK; 7656349Sqs148142 int nregs; 7666349Sqs148142 7676349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs")); 7686349Sqs148142 7696349Sqs148142 if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS) 7706349Sqs148142 return (HXGE_ERROR); 7716349Sqs148142 7726349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs)); 7736349Sqs148142 7746349Sqs148142 hxgep->dev_regs = NULL; 7756349Sqs148142 dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 7766349Sqs148142 dev_regs->hxge_regh = NULL; 7776349Sqs148142 dev_regs->hxge_pciregh = NULL; 7786349Sqs148142 dev_regs->hxge_msix_regh = NULL; 7796349Sqs148142 7806349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 0, ®size); 7816349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7826349Sqs148142 "hxge_map_regs: pci config size 0x%x", regsize)); 7836349Sqs148142 7846349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 0, 7856349Sqs148142 (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0, 7866349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh); 7876349Sqs148142 if (ddi_status != DDI_SUCCESS) { 7886349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7896349Sqs148142 "ddi_map_regs, hxge bus config regs failed")); 7906349Sqs148142 goto hxge_map_regs_fail0; 7916349Sqs148142 } 7926349Sqs148142 7936349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7946349Sqs148142 "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx", 7956349Sqs148142 dev_regs->hxge_pciregp, 7966349Sqs148142 dev_regs->hxge_pciregh)); 7976349Sqs148142 7986349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 1, ®size); 7996349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8006349Sqs148142 "hxge_map_regs: pio size 0x%x", regsize)); 8016349Sqs148142 8026349Sqs148142 /* set up the device mapped register */ 8036349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 1, 8046349Sqs148142 (caddr_t *)&(dev_regs->hxge_regp), 0, 0, 8056349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh); 8066349Sqs148142 8076349Sqs148142 if (ddi_status != DDI_SUCCESS) { 8086349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8096349Sqs148142 "ddi_map_regs for Hydra global reg failed")); 8106349Sqs148142 goto hxge_map_regs_fail1; 8116349Sqs148142 } 8126349Sqs148142 8136349Sqs148142 /* set up the msi/msi-x mapped register */ 8146349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 2, ®size); 8156349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8166349Sqs148142 "hxge_map_regs: msix size 0x%x", regsize)); 8176349Sqs148142 8186349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 2, 8196349Sqs148142 (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0, 8206349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh); 8216349Sqs148142 8226349Sqs148142 if (ddi_status != DDI_SUCCESS) { 8236349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8246349Sqs148142 "ddi_map_regs for msi reg failed")); 8256349Sqs148142 goto hxge_map_regs_fail2; 8266349Sqs148142 } 8276349Sqs148142 8286349Sqs148142 hxgep->dev_regs = dev_regs; 8296349Sqs148142 8306349Sqs148142 HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh); 8316349Sqs148142 HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp); 8326349Sqs148142 HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh); 8336349Sqs148142 HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp); 8346349Sqs148142 8356349Sqs148142 HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 8366349Sqs148142 HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 8376349Sqs148142 8386349Sqs148142 HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 8396349Sqs148142 HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 8406349Sqs148142 8416349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx " 8426349Sqs148142 " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh)); 8436349Sqs148142 8446349Sqs148142 goto hxge_map_regs_exit; 8456349Sqs148142 8466349Sqs148142 hxge_map_regs_fail3: 8476349Sqs148142 if (dev_regs->hxge_msix_regh) { 8486349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_msix_regh); 8496349Sqs148142 } 8506349Sqs148142 8516349Sqs148142 hxge_map_regs_fail2: 8526349Sqs148142 if (dev_regs->hxge_regh) { 8536349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_regh); 8546349Sqs148142 } 8556349Sqs148142 8566349Sqs148142 hxge_map_regs_fail1: 8576349Sqs148142 if (dev_regs->hxge_pciregh) { 8586349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_pciregh); 8596349Sqs148142 } 8606349Sqs148142 8616349Sqs148142 hxge_map_regs_fail0: 8626349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory")); 8636349Sqs148142 kmem_free(dev_regs, sizeof (dev_regs_t)); 8646349Sqs148142 8656349Sqs148142 hxge_map_regs_exit: 8666349Sqs148142 if (ddi_status != DDI_SUCCESS) 8676349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 8686349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs")); 8696349Sqs148142 return (status); 8706349Sqs148142 } 8716349Sqs148142 8726349Sqs148142 static void 8736349Sqs148142 hxge_unmap_regs(p_hxge_t hxgep) 8746349Sqs148142 { 8756349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs")); 8766349Sqs148142 if (hxgep->dev_regs) { 8776349Sqs148142 if (hxgep->dev_regs->hxge_pciregh) { 8786349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8796349Sqs148142 "==> hxge_unmap_regs: bus")); 8806349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh); 8816349Sqs148142 hxgep->dev_regs->hxge_pciregh = NULL; 8826349Sqs148142 } 8836349Sqs148142 8846349Sqs148142 if (hxgep->dev_regs->hxge_regh) { 8856349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8866349Sqs148142 "==> hxge_unmap_regs: device registers")); 8876349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_regh); 8886349Sqs148142 hxgep->dev_regs->hxge_regh = NULL; 8896349Sqs148142 } 8906349Sqs148142 8916349Sqs148142 if (hxgep->dev_regs->hxge_msix_regh) { 8926349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8936349Sqs148142 "==> hxge_unmap_regs: device interrupts")); 8946349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh); 8956349Sqs148142 hxgep->dev_regs->hxge_msix_regh = NULL; 8966349Sqs148142 } 8976349Sqs148142 kmem_free(hxgep->dev_regs, sizeof (dev_regs_t)); 8986349Sqs148142 hxgep->dev_regs = NULL; 8996349Sqs148142 } 9006349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs")); 9016349Sqs148142 } 9026349Sqs148142 9036349Sqs148142 static hxge_status_t 9046349Sqs148142 hxge_setup_mutexes(p_hxge_t hxgep) 9056349Sqs148142 { 9066349Sqs148142 int ddi_status = DDI_SUCCESS; 9076349Sqs148142 hxge_status_t status = HXGE_OK; 9086349Sqs148142 9096349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes")); 9106349Sqs148142 9116349Sqs148142 /* 9126349Sqs148142 * Get the interrupt cookie so the mutexes can be Initialised. 9136349Sqs148142 */ 9146349Sqs148142 ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0, 9156349Sqs148142 &hxgep->interrupt_cookie); 9166349Sqs148142 9176349Sqs148142 if (ddi_status != DDI_SUCCESS) { 9186349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9196349Sqs148142 "<== hxge_setup_mutexes: failed 0x%x", ddi_status)); 9206349Sqs148142 goto hxge_setup_mutexes_exit; 9216349Sqs148142 } 9226349Sqs148142 9236349Sqs148142 /* 9246349Sqs148142 * Initialize mutex's for this device. 9256349Sqs148142 */ 9266349Sqs148142 MUTEX_INIT(hxgep->genlock, NULL, 9276349Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 9286349Sqs148142 MUTEX_INIT(&hxgep->ouraddr_lock, NULL, 9296349Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 9306349Sqs148142 RW_INIT(&hxgep->filter_lock, NULL, 9316349Sqs148142 RW_DRIVER, (void *) hxgep->interrupt_cookie); 9326864Sqs148142 MUTEX_INIT(&hxgep->pio_lock, NULL, 9336864Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 9347584SQiyan.Sun@Sun.COM MUTEX_INIT(&hxgep->timeout.lock, NULL, 9357584SQiyan.Sun@Sun.COM MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 9366349Sqs148142 9376349Sqs148142 hxge_setup_mutexes_exit: 9386349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 9396349Sqs148142 "<== hxge_setup_mutexes status = %x", status)); 9406349Sqs148142 9416349Sqs148142 if (ddi_status != DDI_SUCCESS) 9426349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 9436349Sqs148142 9446349Sqs148142 return (status); 9456349Sqs148142 } 9466349Sqs148142 9476349Sqs148142 static void 9486349Sqs148142 hxge_destroy_mutexes(p_hxge_t hxgep) 9496349Sqs148142 { 9506349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes")); 9516349Sqs148142 RW_DESTROY(&hxgep->filter_lock); 9526349Sqs148142 MUTEX_DESTROY(&hxgep->ouraddr_lock); 9536349Sqs148142 MUTEX_DESTROY(hxgep->genlock); 9546864Sqs148142 MUTEX_DESTROY(&hxgep->pio_lock); 9557584SQiyan.Sun@Sun.COM MUTEX_DESTROY(&hxgep->timeout.lock); 9566349Sqs148142 9576349Sqs148142 if (hxge_debug_init == 1) { 9586349Sqs148142 MUTEX_DESTROY(&hxgedebuglock); 9596349Sqs148142 hxge_debug_init = 0; 9606349Sqs148142 } 9616349Sqs148142 9626349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes")); 9636349Sqs148142 } 9646349Sqs148142 9656349Sqs148142 hxge_status_t 9666349Sqs148142 hxge_init(p_hxge_t hxgep) 9676349Sqs148142 { 9686349Sqs148142 hxge_status_t status = HXGE_OK; 9696349Sqs148142 9706349Sqs148142 HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init")); 9716349Sqs148142 9726349Sqs148142 if (hxgep->drv_state & STATE_HW_INITIALIZED) { 9736349Sqs148142 return (status); 9746349Sqs148142 } 9756349Sqs148142 9766349Sqs148142 /* 9776349Sqs148142 * Allocate system memory for the receive/transmit buffer blocks and 9786349Sqs148142 * receive/transmit descriptor rings. 9796349Sqs148142 */ 9806349Sqs148142 status = hxge_alloc_mem_pool(hxgep); 9816349Sqs148142 if (status != HXGE_OK) { 9826349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n")); 9836349Sqs148142 goto hxge_init_fail1; 9846349Sqs148142 } 9856349Sqs148142 9866349Sqs148142 /* 9876349Sqs148142 * Initialize and enable TXDMA channels. 9886349Sqs148142 */ 9896349Sqs148142 status = hxge_init_txdma_channels(hxgep); 9906349Sqs148142 if (status != HXGE_OK) { 9916349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n")); 9926349Sqs148142 goto hxge_init_fail3; 9936349Sqs148142 } 9946349Sqs148142 9956349Sqs148142 /* 9966349Sqs148142 * Initialize and enable RXDMA channels. 9976349Sqs148142 */ 9986349Sqs148142 status = hxge_init_rxdma_channels(hxgep); 9996349Sqs148142 if (status != HXGE_OK) { 10006349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n")); 10016349Sqs148142 goto hxge_init_fail4; 10026349Sqs148142 } 10036349Sqs148142 10046349Sqs148142 /* 10056349Sqs148142 * Initialize TCAM 10066349Sqs148142 */ 10076349Sqs148142 status = hxge_classify_init(hxgep); 10086349Sqs148142 if (status != HXGE_OK) { 10096349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n")); 10106349Sqs148142 goto hxge_init_fail5; 10116349Sqs148142 } 10126349Sqs148142 10136349Sqs148142 /* 10146349Sqs148142 * Initialize the VMAC block. 10156349Sqs148142 */ 10166349Sqs148142 status = hxge_vmac_init(hxgep); 10176349Sqs148142 if (status != HXGE_OK) { 10186349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n")); 10196349Sqs148142 goto hxge_init_fail5; 10206349Sqs148142 } 10216349Sqs148142 10226349Sqs148142 /* Bringup - this may be unnecessary when PXE and FCODE available */ 10236349Sqs148142 status = hxge_pfc_set_default_mac_addr(hxgep); 10246349Sqs148142 if (status != HXGE_OK) { 10256349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 10266349Sqs148142 "Default Address Failure\n")); 10276349Sqs148142 goto hxge_init_fail5; 10286349Sqs148142 } 10296349Sqs148142 10306349Sqs148142 hxge_intrs_enable(hxgep); 10316349Sqs148142 10326349Sqs148142 /* 10336349Sqs148142 * Enable hardware interrupts. 10346349Sqs148142 */ 10356349Sqs148142 hxge_intr_hw_enable(hxgep); 10366349Sqs148142 hxgep->drv_state |= STATE_HW_INITIALIZED; 10376349Sqs148142 10386349Sqs148142 goto hxge_init_exit; 10396349Sqs148142 10406349Sqs148142 hxge_init_fail5: 10416349Sqs148142 hxge_uninit_rxdma_channels(hxgep); 10426349Sqs148142 hxge_init_fail4: 10436349Sqs148142 hxge_uninit_txdma_channels(hxgep); 10446349Sqs148142 hxge_init_fail3: 10456349Sqs148142 hxge_free_mem_pool(hxgep); 10466349Sqs148142 hxge_init_fail1: 10476349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 10486349Sqs148142 "<== hxge_init status (failed) = 0x%08x", status)); 10496349Sqs148142 return (status); 10506349Sqs148142 10516349Sqs148142 hxge_init_exit: 10526349Sqs148142 10536349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x", 10546349Sqs148142 status)); 10556349Sqs148142 10566349Sqs148142 return (status); 10576349Sqs148142 } 10586349Sqs148142 10596349Sqs148142 timeout_id_t 10606349Sqs148142 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec) 10616349Sqs148142 { 10626349Sqs148142 if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) { 10636349Sqs148142 return (timeout(func, (caddr_t)hxgep, 10646349Sqs148142 drv_usectohz(1000 * msec))); 10656349Sqs148142 } 10666349Sqs148142 return (NULL); 10676349Sqs148142 } 10686349Sqs148142 10696349Sqs148142 /*ARGSUSED*/ 10706349Sqs148142 void 10716349Sqs148142 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid) 10726349Sqs148142 { 10736349Sqs148142 if (timerid) { 10746349Sqs148142 (void) untimeout(timerid); 10756349Sqs148142 } 10766349Sqs148142 } 10776349Sqs148142 10786349Sqs148142 void 10796349Sqs148142 hxge_uninit(p_hxge_t hxgep) 10806349Sqs148142 { 10816349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit")); 10826349Sqs148142 10836349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 10846349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 10856349Sqs148142 "==> hxge_uninit: not initialized")); 10866349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 10876349Sqs148142 return; 10886349Sqs148142 } 10896349Sqs148142 10906349Sqs148142 /* Stop timer */ 10916349Sqs148142 if (hxgep->hxge_timerid) { 10926349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 10936349Sqs148142 hxgep->hxge_timerid = 0; 10946349Sqs148142 } 10956349Sqs148142 10966349Sqs148142 (void) hxge_intr_hw_disable(hxgep); 10976349Sqs148142 10986349Sqs148142 /* Reset the receive VMAC side. */ 10996349Sqs148142 (void) hxge_rx_vmac_disable(hxgep); 11006349Sqs148142 11016349Sqs148142 /* Free classification resources */ 11026349Sqs148142 (void) hxge_classify_uninit(hxgep); 11036349Sqs148142 11046349Sqs148142 /* Reset the transmit/receive DMA side. */ 11056349Sqs148142 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP); 11066349Sqs148142 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP); 11076349Sqs148142 11086349Sqs148142 hxge_uninit_txdma_channels(hxgep); 11096349Sqs148142 hxge_uninit_rxdma_channels(hxgep); 11106349Sqs148142 11116349Sqs148142 /* Reset the transmit VMAC side. */ 11126349Sqs148142 (void) hxge_tx_vmac_disable(hxgep); 11136349Sqs148142 11146349Sqs148142 hxge_free_mem_pool(hxgep); 11156349Sqs148142 11166349Sqs148142 hxgep->drv_state &= ~STATE_HW_INITIALIZED; 11176349Sqs148142 11186349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 11196349Sqs148142 } 11206349Sqs148142 11216349Sqs148142 void 11226349Sqs148142 hxge_get64(p_hxge_t hxgep, p_mblk_t mp) 11236349Sqs148142 { 11246349Sqs148142 #if defined(__i386) 11256349Sqs148142 size_t reg; 11266349Sqs148142 #else 11276349Sqs148142 uint64_t reg; 11286349Sqs148142 #endif 11296349Sqs148142 uint64_t regdata; 11306349Sqs148142 int i, retry; 11316349Sqs148142 11326349Sqs148142 bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 11336349Sqs148142 regdata = 0; 11346349Sqs148142 retry = 1; 11356349Sqs148142 11366349Sqs148142 for (i = 0; i < retry; i++) { 11376349Sqs148142 HXGE_REG_RD64(hxgep->hpi_handle, reg, ®data); 11386349Sqs148142 } 11396349Sqs148142 bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 11406349Sqs148142 } 11416349Sqs148142 11426349Sqs148142 void 11436349Sqs148142 hxge_put64(p_hxge_t hxgep, p_mblk_t mp) 11446349Sqs148142 { 11456349Sqs148142 #if defined(__i386) 11466349Sqs148142 size_t reg; 11476349Sqs148142 #else 11486349Sqs148142 uint64_t reg; 11496349Sqs148142 #endif 11506349Sqs148142 uint64_t buf[2]; 11516349Sqs148142 11526349Sqs148142 bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 11536349Sqs148142 #if defined(__i386) 11546349Sqs148142 reg = (size_t)buf[0]; 11556349Sqs148142 #else 11566349Sqs148142 reg = buf[0]; 11576349Sqs148142 #endif 11586349Sqs148142 11596349Sqs148142 HXGE_HPI_PIO_WRITE64(hxgep->hpi_handle, reg, buf[1]); 11606349Sqs148142 } 11616349Sqs148142 11626349Sqs148142 /*ARGSUSED*/ 11636349Sqs148142 /*VARARGS*/ 11646349Sqs148142 void 11656349Sqs148142 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...) 11666349Sqs148142 { 11676349Sqs148142 char msg_buffer[1048]; 11686349Sqs148142 char prefix_buffer[32]; 11696349Sqs148142 int instance; 11706349Sqs148142 uint64_t debug_level; 11716349Sqs148142 int cmn_level = CE_CONT; 11726349Sqs148142 va_list ap; 11736349Sqs148142 11746349Sqs148142 debug_level = (hxgep == NULL) ? hxge_debug_level : 11756349Sqs148142 hxgep->hxge_debug_level; 11766349Sqs148142 11776349Sqs148142 if ((level & debug_level) || (level == HXGE_NOTE) || 11786349Sqs148142 (level == HXGE_ERR_CTL)) { 11796349Sqs148142 /* do the msg processing */ 11806349Sqs148142 if (hxge_debug_init == 0) { 11816349Sqs148142 MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL); 11826349Sqs148142 hxge_debug_init = 1; 11836349Sqs148142 } 11846349Sqs148142 11856349Sqs148142 MUTEX_ENTER(&hxgedebuglock); 11866349Sqs148142 11876349Sqs148142 if ((level & HXGE_NOTE)) { 11886349Sqs148142 cmn_level = CE_NOTE; 11896349Sqs148142 } 11906349Sqs148142 11916349Sqs148142 if (level & HXGE_ERR_CTL) { 11926349Sqs148142 cmn_level = CE_WARN; 11936349Sqs148142 } 11946349Sqs148142 11956349Sqs148142 va_start(ap, fmt); 11966349Sqs148142 (void) vsprintf(msg_buffer, fmt, ap); 11976349Sqs148142 va_end(ap); 11986349Sqs148142 11996349Sqs148142 if (hxgep == NULL) { 12006349Sqs148142 instance = -1; 12016349Sqs148142 (void) sprintf(prefix_buffer, "%s :", "hxge"); 12026349Sqs148142 } else { 12036349Sqs148142 instance = hxgep->instance; 12046349Sqs148142 (void) sprintf(prefix_buffer, 12056349Sqs148142 "%s%d :", "hxge", instance); 12066349Sqs148142 } 12076349Sqs148142 12086349Sqs148142 MUTEX_EXIT(&hxgedebuglock); 12096349Sqs148142 cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer); 12106349Sqs148142 } 12116349Sqs148142 } 12126349Sqs148142 12136349Sqs148142 char * 12146349Sqs148142 hxge_dump_packet(char *addr, int size) 12156349Sqs148142 { 12166349Sqs148142 uchar_t *ap = (uchar_t *)addr; 12176349Sqs148142 int i; 12186349Sqs148142 static char etherbuf[1024]; 12196349Sqs148142 char *cp = etherbuf; 12206349Sqs148142 char digits[] = "0123456789abcdef"; 12216349Sqs148142 12226349Sqs148142 if (!size) 12236349Sqs148142 size = 60; 12246349Sqs148142 12256349Sqs148142 if (size > MAX_DUMP_SZ) { 12266349Sqs148142 /* Dump the leading bytes */ 12276349Sqs148142 for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 12286349Sqs148142 if (*ap > 0x0f) 12296349Sqs148142 *cp++ = digits[*ap >> 4]; 12306349Sqs148142 *cp++ = digits[*ap++ & 0xf]; 12316349Sqs148142 *cp++ = ':'; 12326349Sqs148142 } 12336349Sqs148142 for (i = 0; i < 20; i++) 12346349Sqs148142 *cp++ = '.'; 12356349Sqs148142 /* Dump the last MAX_DUMP_SZ/2 bytes */ 12366349Sqs148142 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2)); 12376349Sqs148142 for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 12386349Sqs148142 if (*ap > 0x0f) 12396349Sqs148142 *cp++ = digits[*ap >> 4]; 12406349Sqs148142 *cp++ = digits[*ap++ & 0xf]; 12416349Sqs148142 *cp++ = ':'; 12426349Sqs148142 } 12436349Sqs148142 } else { 12446349Sqs148142 for (i = 0; i < size; i++) { 12456349Sqs148142 if (*ap > 0x0f) 12466349Sqs148142 *cp++ = digits[*ap >> 4]; 12476349Sqs148142 *cp++ = digits[*ap++ & 0xf]; 12486349Sqs148142 *cp++ = ':'; 12496349Sqs148142 } 12506349Sqs148142 } 12516349Sqs148142 *--cp = 0; 12526349Sqs148142 return (etherbuf); 12536349Sqs148142 } 12546349Sqs148142 12556349Sqs148142 static void 12566349Sqs148142 hxge_suspend(p_hxge_t hxgep) 12576349Sqs148142 { 12586349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend")); 12596349Sqs148142 12606349Sqs148142 hxge_intrs_disable(hxgep); 12616349Sqs148142 hxge_destroy_dev(hxgep); 12626349Sqs148142 12637584SQiyan.Sun@Sun.COM /* Stop the link status timer */ 12647584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock); 12657584SQiyan.Sun@Sun.COM if (hxgep->timeout.id) 12667584SQiyan.Sun@Sun.COM (void) untimeout(hxgep->timeout.id); 12677584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock); 12687584SQiyan.Sun@Sun.COM 12696349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend")); 12706349Sqs148142 } 12716349Sqs148142 12726349Sqs148142 static hxge_status_t 12736349Sqs148142 hxge_resume(p_hxge_t hxgep) 12746349Sqs148142 { 12756349Sqs148142 hxge_status_t status = HXGE_OK; 12766349Sqs148142 12776349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume")); 12786349Sqs148142 hxgep->suspended = DDI_RESUME; 12796349Sqs148142 12806349Sqs148142 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START); 12816349Sqs148142 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START); 12826349Sqs148142 12836349Sqs148142 (void) hxge_rx_vmac_enable(hxgep); 12846349Sqs148142 (void) hxge_tx_vmac_enable(hxgep); 12856349Sqs148142 12866349Sqs148142 hxge_intrs_enable(hxgep); 12876349Sqs148142 12886349Sqs148142 hxgep->suspended = 0; 12896349Sqs148142 12907584SQiyan.Sun@Sun.COM /* Resume the link status timer */ 12917584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock); 12927584SQiyan.Sun@Sun.COM hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 12937584SQiyan.Sun@Sun.COM hxgep->timeout.ticks); 12947584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock); 12957584SQiyan.Sun@Sun.COM 12966349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 12976349Sqs148142 "<== hxge_resume status = 0x%x", status)); 12986349Sqs148142 12996349Sqs148142 return (status); 13006349Sqs148142 } 13016349Sqs148142 13026349Sqs148142 hxge_status_t 13036349Sqs148142 hxge_setup_dev(p_hxge_t hxgep) 13046349Sqs148142 { 13056349Sqs148142 hxge_status_t status = HXGE_OK; 13066349Sqs148142 13076349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev")); 13086349Sqs148142 13096349Sqs148142 status = hxge_link_init(hxgep); 13106349Sqs148142 if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) { 13116349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 13126349Sqs148142 "Bad register acc handle")); 13136349Sqs148142 status = HXGE_ERROR; 13146349Sqs148142 } 13156349Sqs148142 13166349Sqs148142 if (status != HXGE_OK) { 13176349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, 13186349Sqs148142 " hxge_setup_dev status (link init 0x%08x)", status)); 13196349Sqs148142 goto hxge_setup_dev_exit; 13206349Sqs148142 } 13216349Sqs148142 13226349Sqs148142 hxge_setup_dev_exit: 13236349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13246349Sqs148142 "<== hxge_setup_dev status = 0x%08x", status)); 13256349Sqs148142 13266349Sqs148142 return (status); 13276349Sqs148142 } 13286349Sqs148142 13296349Sqs148142 static void 13306349Sqs148142 hxge_destroy_dev(p_hxge_t hxgep) 13316349Sqs148142 { 13326349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev")); 13336349Sqs148142 13346349Sqs148142 (void) hxge_hw_stop(hxgep); 13356349Sqs148142 13366349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev")); 13376349Sqs148142 } 13386349Sqs148142 13396349Sqs148142 static hxge_status_t 13406349Sqs148142 hxge_setup_system_dma_pages(p_hxge_t hxgep) 13416349Sqs148142 { 13426349Sqs148142 int ddi_status = DDI_SUCCESS; 13436349Sqs148142 uint_t count; 13446349Sqs148142 ddi_dma_cookie_t cookie; 13456349Sqs148142 uint_t iommu_pagesize; 13466349Sqs148142 hxge_status_t status = HXGE_OK; 13476349Sqs148142 13486349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages")); 13496349Sqs148142 13506349Sqs148142 hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1); 13516349Sqs148142 iommu_pagesize = dvma_pagesize(hxgep->dip); 13526349Sqs148142 13536349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13546349Sqs148142 " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 13556349Sqs148142 " default_block_size %d iommu_pagesize %d", 13566349Sqs148142 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 13576349Sqs148142 hxgep->rx_default_block_size, iommu_pagesize)); 13586349Sqs148142 13596349Sqs148142 if (iommu_pagesize != 0) { 13606349Sqs148142 if (hxgep->sys_page_sz == iommu_pagesize) { 13616349Sqs148142 /* Hydra support up to 8K pages */ 13626349Sqs148142 if (iommu_pagesize > 0x2000) 13636349Sqs148142 hxgep->sys_page_sz = 0x2000; 13646349Sqs148142 } else { 13656349Sqs148142 if (hxgep->sys_page_sz > iommu_pagesize) 13666349Sqs148142 hxgep->sys_page_sz = iommu_pagesize; 13676349Sqs148142 } 13686349Sqs148142 } 13696349Sqs148142 13706349Sqs148142 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 13716349Sqs148142 13726349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13736349Sqs148142 "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 13746349Sqs148142 "default_block_size %d page mask %d", 13756349Sqs148142 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 13766349Sqs148142 hxgep->rx_default_block_size, hxgep->sys_page_mask)); 13776349Sqs148142 13786349Sqs148142 switch (hxgep->sys_page_sz) { 13796349Sqs148142 default: 13806349Sqs148142 hxgep->sys_page_sz = 0x1000; 13816349Sqs148142 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 13826349Sqs148142 hxgep->rx_default_block_size = 0x1000; 13836349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_4K; 13846349Sqs148142 break; 13856349Sqs148142 case 0x1000: 13866349Sqs148142 hxgep->rx_default_block_size = 0x1000; 13876349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_4K; 13886349Sqs148142 break; 13896349Sqs148142 case 0x2000: 13906349Sqs148142 hxgep->rx_default_block_size = 0x2000; 13916349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_8K; 13926349Sqs148142 break; 13936349Sqs148142 } 13946349Sqs148142 13956349Sqs148142 hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 13966349Sqs148142 hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 13976349Sqs148142 13986349Sqs148142 /* 13996349Sqs148142 * Get the system DMA burst size. 14006349Sqs148142 */ 14016349Sqs148142 ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr, 14026349Sqs148142 DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle); 14036349Sqs148142 if (ddi_status != DDI_SUCCESS) { 14046349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 14056349Sqs148142 "ddi_dma_alloc_handle: failed status 0x%x", ddi_status)); 14066349Sqs148142 goto hxge_get_soft_properties_exit; 14076349Sqs148142 } 14086349Sqs148142 14096349Sqs148142 ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL, 14106349Sqs148142 (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle), 14116349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0, 14126349Sqs148142 &cookie, &count); 14136349Sqs148142 if (ddi_status != DDI_DMA_MAPPED) { 14146349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 14156349Sqs148142 "Binding spare handle to find system burstsize failed.")); 14166349Sqs148142 ddi_status = DDI_FAILURE; 14176349Sqs148142 goto hxge_get_soft_properties_fail1; 14186349Sqs148142 } 14196349Sqs148142 14206349Sqs148142 hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle); 14216349Sqs148142 (void) ddi_dma_unbind_handle(hxgep->dmasparehandle); 14226349Sqs148142 14236349Sqs148142 hxge_get_soft_properties_fail1: 14246349Sqs148142 ddi_dma_free_handle(&hxgep->dmasparehandle); 14256349Sqs148142 14266349Sqs148142 hxge_get_soft_properties_exit: 14276349Sqs148142 14286349Sqs148142 if (ddi_status != DDI_SUCCESS) 14296349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 14306349Sqs148142 14316349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 14326349Sqs148142 "<== hxge_setup_system_dma_pages status = 0x%08x", status)); 14336349Sqs148142 14346349Sqs148142 return (status); 14356349Sqs148142 } 14366349Sqs148142 14376349Sqs148142 hxge_status_t 14386349Sqs148142 hxge_alloc_mem_pool(p_hxge_t hxgep) 14396349Sqs148142 { 14406349Sqs148142 hxge_status_t status = HXGE_OK; 14416349Sqs148142 14426349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool")); 14436349Sqs148142 14446349Sqs148142 status = hxge_alloc_rx_mem_pool(hxgep); 14456349Sqs148142 if (status != HXGE_OK) { 14466349Sqs148142 return (HXGE_ERROR); 14476349Sqs148142 } 14486349Sqs148142 14496349Sqs148142 status = hxge_alloc_tx_mem_pool(hxgep); 14506349Sqs148142 if (status != HXGE_OK) { 14516349Sqs148142 hxge_free_rx_mem_pool(hxgep); 14526349Sqs148142 return (HXGE_ERROR); 14536349Sqs148142 } 14546349Sqs148142 14556349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool")); 14566349Sqs148142 return (HXGE_OK); 14576349Sqs148142 } 14586349Sqs148142 14596349Sqs148142 static void 14606349Sqs148142 hxge_free_mem_pool(p_hxge_t hxgep) 14616349Sqs148142 { 14626349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool")); 14636349Sqs148142 14646349Sqs148142 hxge_free_rx_mem_pool(hxgep); 14656349Sqs148142 hxge_free_tx_mem_pool(hxgep); 14666349Sqs148142 14676349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool")); 14686349Sqs148142 } 14696349Sqs148142 14706349Sqs148142 static hxge_status_t 14716349Sqs148142 hxge_alloc_rx_mem_pool(p_hxge_t hxgep) 14726349Sqs148142 { 14736349Sqs148142 int i, j; 14746349Sqs148142 uint32_t ndmas, st_rdc; 14756349Sqs148142 p_hxge_dma_pt_cfg_t p_all_cfgp; 14766349Sqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 14776349Sqs148142 p_hxge_dma_pool_t dma_poolp; 14786349Sqs148142 p_hxge_dma_common_t *dma_buf_p; 14797618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rbr_cntl_poolp; 14807618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rbr_cntl_p; 14817618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rcr_cntl_poolp; 14827618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rcr_cntl_p; 14837618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_mbox_cntl_poolp; 14847618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_mbox_cntl_p; 14856349Sqs148142 size_t rx_buf_alloc_size; 14867618SMichael.Speer@Sun.COM size_t rx_rbr_cntl_alloc_size; 14877618SMichael.Speer@Sun.COM size_t rx_rcr_cntl_alloc_size; 14887618SMichael.Speer@Sun.COM size_t rx_mbox_cntl_alloc_size; 14896349Sqs148142 uint32_t *num_chunks; /* per dma */ 14906349Sqs148142 hxge_status_t status = HXGE_OK; 14916349Sqs148142 14926349Sqs148142 uint32_t hxge_port_rbr_size; 14936349Sqs148142 uint32_t hxge_port_rbr_spare_size; 14946349Sqs148142 uint32_t hxge_port_rcr_size; 14956349Sqs148142 14966349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool")); 14976349Sqs148142 14986349Sqs148142 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 14996349Sqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 15006349Sqs148142 st_rdc = p_cfgp->start_rdc; 15016349Sqs148142 ndmas = p_cfgp->max_rdcs; 15026349Sqs148142 15036349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 15046349Sqs148142 " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 15056349Sqs148142 15066349Sqs148142 /* 15076349Sqs148142 * Allocate memory for each receive DMA channel. 15086349Sqs148142 */ 15096349Sqs148142 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 15106349Sqs148142 KM_SLEEP); 15116349Sqs148142 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 15126349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 15136349Sqs148142 15147618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp = (p_hxge_dma_pool_t) 15157618SMichael.Speer@Sun.COM KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 15167618SMichael.Speer@Sun.COM dma_rbr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 15177618SMichael.Speer@Sun.COM sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 15187618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp = (p_hxge_dma_pool_t) 15196349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 15207618SMichael.Speer@Sun.COM dma_rcr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 15217618SMichael.Speer@Sun.COM sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 15227618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp = (p_hxge_dma_pool_t) 15237618SMichael.Speer@Sun.COM KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 15247618SMichael.Speer@Sun.COM dma_mbox_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 15256349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 15266349Sqs148142 15276349Sqs148142 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 15286349Sqs148142 KM_SLEEP); 15296349Sqs148142 15306349Sqs148142 /* 15316349Sqs148142 * Assume that each DMA channel will be configured with default block 15326349Sqs148142 * size. rbr block counts are mod of batch count (16). 15336349Sqs148142 */ 15346349Sqs148142 hxge_port_rbr_size = p_all_cfgp->rbr_size; 15356349Sqs148142 hxge_port_rcr_size = p_all_cfgp->rcr_size; 15366349Sqs148142 15376349Sqs148142 if (!hxge_port_rbr_size) { 15386349Sqs148142 hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT; 15396349Sqs148142 } 15406349Sqs148142 15416349Sqs148142 if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) { 15426349Sqs148142 hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH * 15436349Sqs148142 (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1)); 15446349Sqs148142 } 15456349Sqs148142 15466349Sqs148142 p_all_cfgp->rbr_size = hxge_port_rbr_size; 15476349Sqs148142 hxge_port_rbr_spare_size = hxge_rbr_spare_size; 15486349Sqs148142 15496349Sqs148142 if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) { 15506349Sqs148142 hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH * 15516349Sqs148142 (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1)); 15526349Sqs148142 } 15536349Sqs148142 15546349Sqs148142 rx_buf_alloc_size = (hxgep->rx_default_block_size * 15556349Sqs148142 (hxge_port_rbr_size + hxge_port_rbr_spare_size)); 15566349Sqs148142 15576349Sqs148142 /* 15586349Sqs148142 * Addresses of receive block ring, receive completion ring and the 15596349Sqs148142 * mailbox must be all cache-aligned (64 bytes). 15606349Sqs148142 */ 15617618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size; 15627618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size *= sizeof (rx_desc_t); 15637618SMichael.Speer@Sun.COM rx_rcr_cntl_alloc_size = sizeof (rcr_entry_t) * hxge_port_rcr_size; 15647618SMichael.Speer@Sun.COM rx_mbox_cntl_alloc_size = sizeof (rxdma_mailbox_t); 15656349Sqs148142 15666349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: " 15676349Sqs148142 "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d " 15686349Sqs148142 "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d", 15696349Sqs148142 hxge_port_rbr_size, hxge_port_rbr_spare_size, 15706349Sqs148142 hxge_port_rcr_size, rx_cntl_alloc_size)); 15716349Sqs148142 15726349Sqs148142 hxgep->hxge_port_rbr_size = hxge_port_rbr_size; 15736349Sqs148142 hxgep->hxge_port_rcr_size = hxge_port_rcr_size; 15746349Sqs148142 15756349Sqs148142 /* 15766349Sqs148142 * Allocate memory for receive buffers and descriptor rings. Replace 15776349Sqs148142 * allocation functions with interface functions provided by the 15786349Sqs148142 * partition manager when it is available. 15796349Sqs148142 */ 15806349Sqs148142 /* 15816349Sqs148142 * Allocate memory for the receive buffer blocks. 15826349Sqs148142 */ 15836349Sqs148142 for (i = 0; i < ndmas; i++) { 15846349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 15856349Sqs148142 " hxge_alloc_rx_mem_pool to alloc mem: " 15866349Sqs148142 " dma %d dma_buf_p %llx &dma_buf_p %llx", 15876349Sqs148142 i, dma_buf_p[i], &dma_buf_p[i])); 15886349Sqs148142 15896349Sqs148142 num_chunks[i] = 0; 15906349Sqs148142 15916349Sqs148142 status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i], 15926349Sqs148142 rx_buf_alloc_size, hxgep->rx_default_block_size, 15936349Sqs148142 &num_chunks[i]); 15946349Sqs148142 if (status != HXGE_OK) { 15956349Sqs148142 break; 15966349Sqs148142 } 15976349Sqs148142 15986349Sqs148142 st_rdc++; 15996349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 16006349Sqs148142 " hxge_alloc_rx_mem_pool DONE alloc mem: " 16016349Sqs148142 "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 16026349Sqs148142 dma_buf_p[i], &dma_buf_p[i])); 16036349Sqs148142 } 16046349Sqs148142 16056349Sqs148142 if (i < ndmas) { 16066349Sqs148142 goto hxge_alloc_rx_mem_fail1; 16076349Sqs148142 } 16086349Sqs148142 16096349Sqs148142 /* 16106349Sqs148142 * Allocate memory for descriptor rings and mailbox. 16116349Sqs148142 */ 16126349Sqs148142 st_rdc = p_cfgp->start_rdc; 16136349Sqs148142 for (j = 0; j < ndmas; j++) { 16147618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 16157618SMichael.Speer@Sun.COM &dma_rbr_cntl_p[j], &hxge_rx_rbr_desc_dma_attr, 16167618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size)) != HXGE_OK) { 16177618SMichael.Speer@Sun.COM break; 16187618SMichael.Speer@Sun.COM } 16197618SMichael.Speer@Sun.COM 16207618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 16217618SMichael.Speer@Sun.COM &dma_rcr_cntl_p[j], &hxge_rx_rcr_desc_dma_attr, 16227618SMichael.Speer@Sun.COM rx_rcr_cntl_alloc_size)) != HXGE_OK) { 16237618SMichael.Speer@Sun.COM break; 16247618SMichael.Speer@Sun.COM } 16257618SMichael.Speer@Sun.COM 16267618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 16277618SMichael.Speer@Sun.COM &dma_mbox_cntl_p[j], &hxge_rx_mbox_dma_attr, 16287618SMichael.Speer@Sun.COM rx_mbox_cntl_alloc_size)) != HXGE_OK) { 16296349Sqs148142 break; 16306349Sqs148142 } 16316349Sqs148142 st_rdc++; 16326349Sqs148142 } 16336349Sqs148142 16346349Sqs148142 if (j < ndmas) { 16356349Sqs148142 goto hxge_alloc_rx_mem_fail2; 16366349Sqs148142 } 16376349Sqs148142 16386349Sqs148142 dma_poolp->ndmas = ndmas; 16396349Sqs148142 dma_poolp->num_chunks = num_chunks; 16406349Sqs148142 dma_poolp->buf_allocated = B_TRUE; 16416349Sqs148142 hxgep->rx_buf_pool_p = dma_poolp; 16426349Sqs148142 dma_poolp->dma_buf_pool_p = dma_buf_p; 16436349Sqs148142 16447618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->ndmas = ndmas; 16457618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->buf_allocated = B_TRUE; 16467618SMichael.Speer@Sun.COM hxgep->rx_rbr_cntl_pool_p = dma_rbr_cntl_poolp; 16477618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->dma_buf_pool_p = dma_rbr_cntl_p; 16487618SMichael.Speer@Sun.COM 16497618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->ndmas = ndmas; 16507618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->buf_allocated = B_TRUE; 16517618SMichael.Speer@Sun.COM hxgep->rx_rcr_cntl_pool_p = dma_rcr_cntl_poolp; 16527618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->dma_buf_pool_p = dma_rcr_cntl_p; 16537618SMichael.Speer@Sun.COM 16547618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->ndmas = ndmas; 16557618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->buf_allocated = B_TRUE; 16567618SMichael.Speer@Sun.COM hxgep->rx_mbox_cntl_pool_p = dma_mbox_cntl_poolp; 16577618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->dma_buf_pool_p = dma_mbox_cntl_p; 16586349Sqs148142 16596349Sqs148142 goto hxge_alloc_rx_mem_pool_exit; 16606349Sqs148142 16616349Sqs148142 hxge_alloc_rx_mem_fail2: 16626349Sqs148142 /* Free control buffers */ 16636349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16646349Sqs148142 "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 16656349Sqs148142 for (; j >= 0; j--) { 16666349Sqs148142 hxge_free_rx_cntl_dma(hxgep, 16677618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_rbr_cntl_p[j]); 16687618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, 16697618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_rcr_cntl_p[j]); 16707618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, 16717618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_mbox_cntl_p[j]); 16726349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16736349Sqs148142 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 16746349Sqs148142 } 16756349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16766349Sqs148142 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 16776349Sqs148142 16786349Sqs148142 hxge_alloc_rx_mem_fail1: 16796349Sqs148142 /* Free data buffers */ 16806349Sqs148142 i--; 16816349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16826349Sqs148142 "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 16836349Sqs148142 for (; i >= 0; i--) { 16846349Sqs148142 hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 16856349Sqs148142 num_chunks[i]); 16866349Sqs148142 } 16876349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16886349Sqs148142 "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 16896349Sqs148142 16906349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 16916349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 16926349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 16937618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t)); 16947618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 16957618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t)); 16967618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 16977618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t)); 16987618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 16996349Sqs148142 17006349Sqs148142 hxge_alloc_rx_mem_pool_exit: 17016349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 17026349Sqs148142 "<== hxge_alloc_rx_mem_pool:status 0x%08x", status)); 17036349Sqs148142 17046349Sqs148142 return (status); 17056349Sqs148142 } 17066349Sqs148142 17076349Sqs148142 static void 17086349Sqs148142 hxge_free_rx_mem_pool(p_hxge_t hxgep) 17096349Sqs148142 { 17106349Sqs148142 uint32_t i, ndmas; 17116349Sqs148142 p_hxge_dma_pool_t dma_poolp; 17126349Sqs148142 p_hxge_dma_common_t *dma_buf_p; 17137618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rbr_cntl_poolp; 17147618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rbr_cntl_p; 17157618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rcr_cntl_poolp; 17167618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rcr_cntl_p; 17177618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_mbox_cntl_poolp; 17187618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_mbox_cntl_p; 17196349Sqs148142 uint32_t *num_chunks; 17206349Sqs148142 17216349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool")); 17226349Sqs148142 17236349Sqs148142 dma_poolp = hxgep->rx_buf_pool_p; 17246349Sqs148142 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 17256349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool " 17266349Sqs148142 "(null rx buf pool or buf not allocated")); 17276349Sqs148142 return; 17286349Sqs148142 } 17296349Sqs148142 17307618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p; 17317618SMichael.Speer@Sun.COM if (dma_rbr_cntl_poolp == NULL || 17327618SMichael.Speer@Sun.COM (!dma_rbr_cntl_poolp->buf_allocated)) { 17336349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17346349Sqs148142 "<== hxge_free_rx_mem_pool " 17357618SMichael.Speer@Sun.COM "(null rbr cntl buf pool or rbr cntl buf not allocated")); 17367618SMichael.Speer@Sun.COM return; 17377618SMichael.Speer@Sun.COM } 17387618SMichael.Speer@Sun.COM 17397618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p; 17407618SMichael.Speer@Sun.COM if (dma_rcr_cntl_poolp == NULL || 17417618SMichael.Speer@Sun.COM (!dma_rcr_cntl_poolp->buf_allocated)) { 17427618SMichael.Speer@Sun.COM HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17437618SMichael.Speer@Sun.COM "<== hxge_free_rx_mem_pool " 17447618SMichael.Speer@Sun.COM "(null rcr cntl buf pool or rcr cntl buf not allocated")); 17457618SMichael.Speer@Sun.COM return; 17467618SMichael.Speer@Sun.COM } 17477618SMichael.Speer@Sun.COM 17487618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p; 17497618SMichael.Speer@Sun.COM if (dma_mbox_cntl_poolp == NULL || 17507618SMichael.Speer@Sun.COM (!dma_mbox_cntl_poolp->buf_allocated)) { 17517618SMichael.Speer@Sun.COM HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17527618SMichael.Speer@Sun.COM "<== hxge_free_rx_mem_pool " 17537618SMichael.Speer@Sun.COM "(null mbox cntl buf pool or mbox cntl buf not allocated")); 17546349Sqs148142 return; 17556349Sqs148142 } 17566349Sqs148142 17576349Sqs148142 dma_buf_p = dma_poolp->dma_buf_pool_p; 17586349Sqs148142 num_chunks = dma_poolp->num_chunks; 17596349Sqs148142 17607618SMichael.Speer@Sun.COM dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p; 17617618SMichael.Speer@Sun.COM dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p; 17627618SMichael.Speer@Sun.COM dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p; 17637618SMichael.Speer@Sun.COM ndmas = dma_rbr_cntl_poolp->ndmas; 17646349Sqs148142 17656349Sqs148142 for (i = 0; i < ndmas; i++) { 17666349Sqs148142 hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 17676349Sqs148142 } 17686349Sqs148142 17696349Sqs148142 for (i = 0; i < ndmas; i++) { 17707618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_rbr_cntl_p[i]); 17717618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_rcr_cntl_p[i]); 17727618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_mbox_cntl_p[i]); 17736349Sqs148142 } 17746349Sqs148142 17756349Sqs148142 for (i = 0; i < ndmas; i++) { 17766349Sqs148142 KMEM_FREE(dma_buf_p[i], 17776349Sqs148142 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 17787618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p[i], sizeof (hxge_dma_common_t)); 17797618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p[i], sizeof (hxge_dma_common_t)); 17807618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p[i], sizeof (hxge_dma_common_t)); 17816349Sqs148142 } 17826349Sqs148142 17836349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 17847618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 17857618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t)); 17867618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 17877618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t)); 17887618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 17897618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t)); 17906349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 17916349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 17926349Sqs148142 17936349Sqs148142 hxgep->rx_buf_pool_p = NULL; 17947618SMichael.Speer@Sun.COM hxgep->rx_rbr_cntl_pool_p = NULL; 17957618SMichael.Speer@Sun.COM hxgep->rx_rcr_cntl_pool_p = NULL; 17967618SMichael.Speer@Sun.COM hxgep->rx_mbox_cntl_pool_p = NULL; 17976349Sqs148142 17986349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool")); 17996349Sqs148142 } 18006349Sqs148142 18016349Sqs148142 static hxge_status_t 18026349Sqs148142 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 18036349Sqs148142 p_hxge_dma_common_t *dmap, 18046349Sqs148142 size_t alloc_size, size_t block_size, uint32_t *num_chunks) 18056349Sqs148142 { 18066349Sqs148142 p_hxge_dma_common_t rx_dmap; 18076349Sqs148142 hxge_status_t status = HXGE_OK; 18086349Sqs148142 size_t total_alloc_size; 18096349Sqs148142 size_t allocated = 0; 18106349Sqs148142 int i, size_index, array_size; 18116349Sqs148142 18126349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma")); 18136349Sqs148142 18146349Sqs148142 rx_dmap = (p_hxge_dma_common_t) 18156349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 18166349Sqs148142 18176349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 18186349Sqs148142 " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 18196349Sqs148142 dma_channel, alloc_size, block_size, dmap)); 18206349Sqs148142 18216349Sqs148142 total_alloc_size = alloc_size; 18226349Sqs148142 18236349Sqs148142 i = 0; 18246349Sqs148142 size_index = 0; 18256349Sqs148142 array_size = sizeof (alloc_sizes) / sizeof (size_t); 18266349Sqs148142 while ((alloc_sizes[size_index] < alloc_size) && 18276349Sqs148142 (size_index < array_size)) 18286349Sqs148142 size_index++; 18296349Sqs148142 if (size_index >= array_size) { 18306349Sqs148142 size_index = array_size - 1; 18316349Sqs148142 } 18326349Sqs148142 18336349Sqs148142 while ((allocated < total_alloc_size) && 18346349Sqs148142 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 18356349Sqs148142 rx_dmap[i].dma_chunk_index = i; 18366349Sqs148142 rx_dmap[i].block_size = block_size; 18376349Sqs148142 rx_dmap[i].alength = alloc_sizes[size_index]; 18386349Sqs148142 rx_dmap[i].orig_alength = rx_dmap[i].alength; 18396349Sqs148142 rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 18406349Sqs148142 rx_dmap[i].dma_channel = dma_channel; 18416349Sqs148142 rx_dmap[i].contig_alloc_type = B_FALSE; 18426349Sqs148142 18436349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 18446349Sqs148142 "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 18456349Sqs148142 "i %d nblocks %d alength %d", 18466349Sqs148142 dma_channel, i, &rx_dmap[i], block_size, 18476349Sqs148142 i, rx_dmap[i].nblocks, rx_dmap[i].alength)); 18486349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 18496349Sqs148142 &hxge_rx_dma_attr, rx_dmap[i].alength, 18506349Sqs148142 &hxge_dev_buf_dma_acc_attr, 18516349Sqs148142 DDI_DMA_READ | DDI_DMA_STREAMING, 18526349Sqs148142 (p_hxge_dma_common_t)(&rx_dmap[i])); 18536349Sqs148142 if (status != HXGE_OK) { 18546349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 18556349Sqs148142 " hxge_alloc_rx_buf_dma: Alloc Failed: " 18566349Sqs148142 " for size: %d", alloc_sizes[size_index])); 18576349Sqs148142 size_index--; 18586349Sqs148142 } else { 18596349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 18606349Sqs148142 " alloc_rx_buf_dma allocated rdc %d " 18616349Sqs148142 "chunk %d size %x dvma %x bufp %llx ", 18626349Sqs148142 dma_channel, i, rx_dmap[i].alength, 18636349Sqs148142 rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 18646349Sqs148142 i++; 18656349Sqs148142 allocated += alloc_sizes[size_index]; 18666349Sqs148142 } 18676349Sqs148142 } 18686349Sqs148142 18696349Sqs148142 if (allocated < total_alloc_size) { 18706349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 18716349Sqs148142 " hxge_alloc_rx_buf_dma failed due to" 18726349Sqs148142 " allocated(%d) < required(%d)", 18736349Sqs148142 allocated, total_alloc_size)); 18746349Sqs148142 goto hxge_alloc_rx_mem_fail1; 18756349Sqs148142 } 18766349Sqs148142 18776349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 18786349Sqs148142 " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i)); 18796349Sqs148142 18806349Sqs148142 *num_chunks = i; 18816349Sqs148142 *dmap = rx_dmap; 18826349Sqs148142 18836349Sqs148142 goto hxge_alloc_rx_mem_exit; 18846349Sqs148142 18856349Sqs148142 hxge_alloc_rx_mem_fail1: 18866349Sqs148142 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 18876349Sqs148142 18886349Sqs148142 hxge_alloc_rx_mem_exit: 18896349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 18906349Sqs148142 "<== hxge_alloc_rx_buf_dma status 0x%08x", status)); 18916349Sqs148142 18926349Sqs148142 return (status); 18936349Sqs148142 } 18946349Sqs148142 18956349Sqs148142 /*ARGSUSED*/ 18966349Sqs148142 static void 18976349Sqs148142 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 18986349Sqs148142 uint32_t num_chunks) 18996349Sqs148142 { 19006349Sqs148142 int i; 19016349Sqs148142 19026349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 19036349Sqs148142 "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 19046349Sqs148142 19056349Sqs148142 for (i = 0; i < num_chunks; i++) { 19066349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 19076349Sqs148142 "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap)); 19086349Sqs148142 hxge_dma_mem_free(dmap++); 19096349Sqs148142 } 19106349Sqs148142 19116349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma")); 19126349Sqs148142 } 19136349Sqs148142 19146349Sqs148142 /*ARGSUSED*/ 19156349Sqs148142 static hxge_status_t 19166349Sqs148142 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 19177618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dmap, struct ddi_dma_attr *attr, size_t size) 19186349Sqs148142 { 19196349Sqs148142 p_hxge_dma_common_t rx_dmap; 19206349Sqs148142 hxge_status_t status = HXGE_OK; 19216349Sqs148142 19226349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma")); 19236349Sqs148142 19246349Sqs148142 rx_dmap = (p_hxge_dma_common_t) 19256349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP); 19266349Sqs148142 19276349Sqs148142 rx_dmap->contig_alloc_type = B_FALSE; 19286349Sqs148142 19296349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 19307618SMichael.Speer@Sun.COM attr, size, &hxge_dev_desc_dma_acc_attr, 19316349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap); 19326349Sqs148142 if (status != HXGE_OK) { 19336349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 19346349Sqs148142 " hxge_alloc_rx_cntl_dma: Alloc Failed: " 19356349Sqs148142 " for size: %d", size)); 19366349Sqs148142 goto hxge_alloc_rx_cntl_dma_fail1; 19376349Sqs148142 } 19386349Sqs148142 19396349Sqs148142 *dmap = rx_dmap; 19406349Sqs148142 19416349Sqs148142 goto hxge_alloc_rx_cntl_dma_exit; 19426349Sqs148142 19436349Sqs148142 hxge_alloc_rx_cntl_dma_fail1: 19446349Sqs148142 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t)); 19456349Sqs148142 19466349Sqs148142 hxge_alloc_rx_cntl_dma_exit: 19476349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 19486349Sqs148142 "<== hxge_alloc_rx_cntl_dma status 0x%08x", status)); 19496349Sqs148142 19506349Sqs148142 return (status); 19516349Sqs148142 } 19526349Sqs148142 19536349Sqs148142 /*ARGSUSED*/ 19546349Sqs148142 static void 19556349Sqs148142 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 19566349Sqs148142 { 19576349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma")); 19586349Sqs148142 19596349Sqs148142 hxge_dma_mem_free(dmap); 19606349Sqs148142 19616349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma")); 19626349Sqs148142 } 19636349Sqs148142 19646349Sqs148142 static hxge_status_t 19656349Sqs148142 hxge_alloc_tx_mem_pool(p_hxge_t hxgep) 19666349Sqs148142 { 19676349Sqs148142 hxge_status_t status = HXGE_OK; 19686349Sqs148142 int i, j; 19696349Sqs148142 uint32_t ndmas, st_tdc; 19706349Sqs148142 p_hxge_dma_pt_cfg_t p_all_cfgp; 19716349Sqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 19726349Sqs148142 p_hxge_dma_pool_t dma_poolp; 19736349Sqs148142 p_hxge_dma_common_t *dma_buf_p; 19746349Sqs148142 p_hxge_dma_pool_t dma_cntl_poolp; 19756349Sqs148142 p_hxge_dma_common_t *dma_cntl_p; 19766349Sqs148142 size_t tx_buf_alloc_size; 19776349Sqs148142 size_t tx_cntl_alloc_size; 19786349Sqs148142 uint32_t *num_chunks; /* per dma */ 19796349Sqs148142 19806349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool")); 19816349Sqs148142 19826349Sqs148142 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 19836349Sqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 19846349Sqs148142 st_tdc = p_cfgp->start_tdc; 19856349Sqs148142 ndmas = p_cfgp->max_tdcs; 19866349Sqs148142 19876349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: " 19886349Sqs148142 "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d", 19896349Sqs148142 p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs)); 19906349Sqs148142 /* 19916349Sqs148142 * Allocate memory for each transmit DMA channel. 19926349Sqs148142 */ 19936349Sqs148142 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 19946349Sqs148142 KM_SLEEP); 19956349Sqs148142 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 19966349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 19976349Sqs148142 19986349Sqs148142 dma_cntl_poolp = (p_hxge_dma_pool_t) 19996349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 20006349Sqs148142 dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 20016349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 20026349Sqs148142 20036349Sqs148142 hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size; 20046349Sqs148142 20056349Sqs148142 /* 20066349Sqs148142 * Assume that each DMA channel will be configured with default 20076349Sqs148142 * transmit bufer size for copying transmit data. (For packet payload 20086349Sqs148142 * over this limit, packets will not be copied.) 20096349Sqs148142 */ 20106349Sqs148142 tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size); 20116349Sqs148142 20126349Sqs148142 /* 20136349Sqs148142 * Addresses of transmit descriptor ring and the mailbox must be all 20146349Sqs148142 * cache-aligned (64 bytes). 20156349Sqs148142 */ 20166349Sqs148142 tx_cntl_alloc_size = hxge_tx_ring_size; 20176349Sqs148142 tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 20186349Sqs148142 tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 20196349Sqs148142 20206349Sqs148142 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 20216349Sqs148142 KM_SLEEP); 20226349Sqs148142 20236349Sqs148142 /* 20246349Sqs148142 * Allocate memory for transmit buffers and descriptor rings. Replace 20256349Sqs148142 * allocation functions with interface functions provided by the 20266349Sqs148142 * partition manager when it is available. 20276349Sqs148142 * 20286349Sqs148142 * Allocate memory for the transmit buffer pool. 20296349Sqs148142 */ 20306349Sqs148142 for (i = 0; i < ndmas; i++) { 20316349Sqs148142 num_chunks[i] = 0; 20326349Sqs148142 status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i], 20336349Sqs148142 tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]); 20346349Sqs148142 if (status != HXGE_OK) { 20356349Sqs148142 break; 20366349Sqs148142 } 20376349Sqs148142 st_tdc++; 20386349Sqs148142 } 20396349Sqs148142 20406349Sqs148142 if (i < ndmas) { 20416349Sqs148142 goto hxge_alloc_tx_mem_pool_fail1; 20426349Sqs148142 } 20436349Sqs148142 20446349Sqs148142 st_tdc = p_cfgp->start_tdc; 20456349Sqs148142 20466349Sqs148142 /* 20476349Sqs148142 * Allocate memory for descriptor rings and mailbox. 20486349Sqs148142 */ 20496349Sqs148142 for (j = 0; j < ndmas; j++) { 20506349Sqs148142 status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j], 20516349Sqs148142 tx_cntl_alloc_size); 20526349Sqs148142 if (status != HXGE_OK) { 20536349Sqs148142 break; 20546349Sqs148142 } 20556349Sqs148142 st_tdc++; 20566349Sqs148142 } 20576349Sqs148142 20586349Sqs148142 if (j < ndmas) { 20596349Sqs148142 goto hxge_alloc_tx_mem_pool_fail2; 20606349Sqs148142 } 20616349Sqs148142 20626349Sqs148142 dma_poolp->ndmas = ndmas; 20636349Sqs148142 dma_poolp->num_chunks = num_chunks; 20646349Sqs148142 dma_poolp->buf_allocated = B_TRUE; 20656349Sqs148142 dma_poolp->dma_buf_pool_p = dma_buf_p; 20666349Sqs148142 hxgep->tx_buf_pool_p = dma_poolp; 20676349Sqs148142 20686349Sqs148142 dma_cntl_poolp->ndmas = ndmas; 20696349Sqs148142 dma_cntl_poolp->buf_allocated = B_TRUE; 20706349Sqs148142 dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 20716349Sqs148142 hxgep->tx_cntl_pool_p = dma_cntl_poolp; 20726349Sqs148142 20736349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, 20746349Sqs148142 "==> hxge_alloc_tx_mem_pool: start_tdc %d " 20756349Sqs148142 "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas)); 20766349Sqs148142 20776349Sqs148142 goto hxge_alloc_tx_mem_pool_exit; 20786349Sqs148142 20796349Sqs148142 hxge_alloc_tx_mem_pool_fail2: 20806349Sqs148142 /* Free control buffers */ 20816349Sqs148142 j--; 20826349Sqs148142 for (; j >= 0; j--) { 20836349Sqs148142 hxge_free_tx_cntl_dma(hxgep, 20846349Sqs148142 (p_hxge_dma_common_t)dma_cntl_p[j]); 20856349Sqs148142 } 20866349Sqs148142 20876349Sqs148142 hxge_alloc_tx_mem_pool_fail1: 20886349Sqs148142 /* Free data buffers */ 20896349Sqs148142 i--; 20906349Sqs148142 for (; i >= 0; i--) { 20916349Sqs148142 hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 20926349Sqs148142 num_chunks[i]); 20936349Sqs148142 } 20946349Sqs148142 20956349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 20966349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 20976349Sqs148142 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 20986349Sqs148142 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 20996349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 21006349Sqs148142 21016349Sqs148142 hxge_alloc_tx_mem_pool_exit: 21026349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, 21036349Sqs148142 "<== hxge_alloc_tx_mem_pool:status 0x%08x", status)); 21046349Sqs148142 21056349Sqs148142 return (status); 21066349Sqs148142 } 21076349Sqs148142 21086349Sqs148142 static hxge_status_t 21096349Sqs148142 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 21106349Sqs148142 p_hxge_dma_common_t *dmap, size_t alloc_size, 21116349Sqs148142 size_t block_size, uint32_t *num_chunks) 21126349Sqs148142 { 21136349Sqs148142 p_hxge_dma_common_t tx_dmap; 21146349Sqs148142 hxge_status_t status = HXGE_OK; 21156349Sqs148142 size_t total_alloc_size; 21166349Sqs148142 size_t allocated = 0; 21176349Sqs148142 int i, size_index, array_size; 21186349Sqs148142 21196349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma")); 21206349Sqs148142 21216349Sqs148142 tx_dmap = (p_hxge_dma_common_t) 21226349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 21236349Sqs148142 21246349Sqs148142 total_alloc_size = alloc_size; 21256349Sqs148142 i = 0; 21266349Sqs148142 size_index = 0; 21276349Sqs148142 array_size = sizeof (alloc_sizes) / sizeof (size_t); 21286349Sqs148142 while ((alloc_sizes[size_index] < alloc_size) && 21296349Sqs148142 (size_index < array_size)) 21306349Sqs148142 size_index++; 21316349Sqs148142 if (size_index >= array_size) { 21326349Sqs148142 size_index = array_size - 1; 21336349Sqs148142 } 21346349Sqs148142 21356349Sqs148142 while ((allocated < total_alloc_size) && 21366349Sqs148142 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 21376349Sqs148142 tx_dmap[i].dma_chunk_index = i; 21386349Sqs148142 tx_dmap[i].block_size = block_size; 21396349Sqs148142 tx_dmap[i].alength = alloc_sizes[size_index]; 21406349Sqs148142 tx_dmap[i].orig_alength = tx_dmap[i].alength; 21416349Sqs148142 tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 21426349Sqs148142 tx_dmap[i].dma_channel = dma_channel; 21436349Sqs148142 tx_dmap[i].contig_alloc_type = B_FALSE; 21446349Sqs148142 21456349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 21466349Sqs148142 &hxge_tx_dma_attr, tx_dmap[i].alength, 21476349Sqs148142 &hxge_dev_buf_dma_acc_attr, 21486349Sqs148142 DDI_DMA_WRITE | DDI_DMA_STREAMING, 21496349Sqs148142 (p_hxge_dma_common_t)(&tx_dmap[i])); 21506349Sqs148142 if (status != HXGE_OK) { 21516349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 21526349Sqs148142 " hxge_alloc_tx_buf_dma: Alloc Failed: " 21536349Sqs148142 " for size: %d", alloc_sizes[size_index])); 21546349Sqs148142 size_index--; 21556349Sqs148142 } else { 21566349Sqs148142 i++; 21576349Sqs148142 allocated += alloc_sizes[size_index]; 21586349Sqs148142 } 21596349Sqs148142 } 21606349Sqs148142 21616349Sqs148142 if (allocated < total_alloc_size) { 21626349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21636349Sqs148142 " hxge_alloc_tx_buf_dma: failed due to" 21646349Sqs148142 " allocated(%d) < required(%d)", 21656349Sqs148142 allocated, total_alloc_size)); 21666349Sqs148142 goto hxge_alloc_tx_mem_fail1; 21676349Sqs148142 } 21686349Sqs148142 21696349Sqs148142 *num_chunks = i; 21706349Sqs148142 *dmap = tx_dmap; 21716349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 21726349Sqs148142 "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 21736349Sqs148142 *dmap, i)); 21746349Sqs148142 goto hxge_alloc_tx_mem_exit; 21756349Sqs148142 21766349Sqs148142 hxge_alloc_tx_mem_fail1: 21776349Sqs148142 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 21786349Sqs148142 21796349Sqs148142 hxge_alloc_tx_mem_exit: 21806349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 21816349Sqs148142 "<== hxge_alloc_tx_buf_dma status 0x%08x", status)); 21826349Sqs148142 21836349Sqs148142 return (status); 21846349Sqs148142 } 21856349Sqs148142 21866349Sqs148142 /*ARGSUSED*/ 21876349Sqs148142 static void 21886349Sqs148142 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 21896349Sqs148142 uint32_t num_chunks) 21906349Sqs148142 { 21916349Sqs148142 int i; 21926349Sqs148142 21936349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma")); 21946349Sqs148142 21956349Sqs148142 for (i = 0; i < num_chunks; i++) { 21966349Sqs148142 hxge_dma_mem_free(dmap++); 21976349Sqs148142 } 21986349Sqs148142 21996349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma")); 22006349Sqs148142 } 22016349Sqs148142 22026349Sqs148142 /*ARGSUSED*/ 22036349Sqs148142 static hxge_status_t 22046349Sqs148142 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 22056349Sqs148142 p_hxge_dma_common_t *dmap, size_t size) 22066349Sqs148142 { 22076349Sqs148142 p_hxge_dma_common_t tx_dmap; 22086349Sqs148142 hxge_status_t status = HXGE_OK; 22096349Sqs148142 22106349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma")); 22116349Sqs148142 22126349Sqs148142 tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t), 22136349Sqs148142 KM_SLEEP); 22146349Sqs148142 22156349Sqs148142 tx_dmap->contig_alloc_type = B_FALSE; 22166349Sqs148142 22176349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 22187618SMichael.Speer@Sun.COM &hxge_tx_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr, 22196349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap); 22206349Sqs148142 if (status != HXGE_OK) { 22216349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22226349Sqs148142 " hxge_alloc_tx_cntl_dma: Alloc Failed: " 22236349Sqs148142 " for size: %d", size)); 22246349Sqs148142 goto hxge_alloc_tx_cntl_dma_fail1; 22256349Sqs148142 } 22266349Sqs148142 22276349Sqs148142 *dmap = tx_dmap; 22286349Sqs148142 22296349Sqs148142 goto hxge_alloc_tx_cntl_dma_exit; 22306349Sqs148142 22316349Sqs148142 hxge_alloc_tx_cntl_dma_fail1: 22326349Sqs148142 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t)); 22336349Sqs148142 22346349Sqs148142 hxge_alloc_tx_cntl_dma_exit: 22356349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 22366349Sqs148142 "<== hxge_alloc_tx_cntl_dma status 0x%08x", status)); 22376349Sqs148142 22386349Sqs148142 return (status); 22396349Sqs148142 } 22406349Sqs148142 22416349Sqs148142 /*ARGSUSED*/ 22426349Sqs148142 static void 22436349Sqs148142 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 22446349Sqs148142 { 22456349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma")); 22466349Sqs148142 22476349Sqs148142 hxge_dma_mem_free(dmap); 22486349Sqs148142 22496349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma")); 22506349Sqs148142 } 22516349Sqs148142 22526349Sqs148142 static void 22536349Sqs148142 hxge_free_tx_mem_pool(p_hxge_t hxgep) 22546349Sqs148142 { 22556349Sqs148142 uint32_t i, ndmas; 22566349Sqs148142 p_hxge_dma_pool_t dma_poolp; 22576349Sqs148142 p_hxge_dma_common_t *dma_buf_p; 22586349Sqs148142 p_hxge_dma_pool_t dma_cntl_poolp; 22596349Sqs148142 p_hxge_dma_common_t *dma_cntl_p; 22606349Sqs148142 uint32_t *num_chunks; 22616349Sqs148142 22626349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool")); 22636349Sqs148142 22646349Sqs148142 dma_poolp = hxgep->tx_buf_pool_p; 22656349Sqs148142 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 22666349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 22676349Sqs148142 "<== hxge_free_tx_mem_pool " 22686349Sqs148142 "(null rx buf pool or buf not allocated")); 22696349Sqs148142 return; 22706349Sqs148142 } 22716349Sqs148142 22726349Sqs148142 dma_cntl_poolp = hxgep->tx_cntl_pool_p; 22736349Sqs148142 if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 22746349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 22756349Sqs148142 "<== hxge_free_tx_mem_pool " 22766349Sqs148142 "(null tx cntl buf pool or cntl buf not allocated")); 22776349Sqs148142 return; 22786349Sqs148142 } 22796349Sqs148142 22806349Sqs148142 dma_buf_p = dma_poolp->dma_buf_pool_p; 22816349Sqs148142 num_chunks = dma_poolp->num_chunks; 22826349Sqs148142 22836349Sqs148142 dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 22846349Sqs148142 ndmas = dma_cntl_poolp->ndmas; 22856349Sqs148142 22866349Sqs148142 for (i = 0; i < ndmas; i++) { 22876349Sqs148142 hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 22886349Sqs148142 } 22896349Sqs148142 22906349Sqs148142 for (i = 0; i < ndmas; i++) { 22916349Sqs148142 hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]); 22926349Sqs148142 } 22936349Sqs148142 22946349Sqs148142 for (i = 0; i < ndmas; i++) { 22956349Sqs148142 KMEM_FREE(dma_buf_p[i], 22966349Sqs148142 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 22976349Sqs148142 KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t)); 22986349Sqs148142 } 22996349Sqs148142 23006349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 23016349Sqs148142 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 23026349Sqs148142 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 23036349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 23046349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 23056349Sqs148142 23066349Sqs148142 hxgep->tx_buf_pool_p = NULL; 23076349Sqs148142 hxgep->tx_cntl_pool_p = NULL; 23086349Sqs148142 23096349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool")); 23106349Sqs148142 } 23116349Sqs148142 23126349Sqs148142 /*ARGSUSED*/ 23136349Sqs148142 static hxge_status_t 23146349Sqs148142 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method, 23156349Sqs148142 struct ddi_dma_attr *dma_attrp, 23166349Sqs148142 size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 23176349Sqs148142 p_hxge_dma_common_t dma_p) 23186349Sqs148142 { 23196349Sqs148142 caddr_t kaddrp; 23206349Sqs148142 int ddi_status = DDI_SUCCESS; 23216349Sqs148142 23226349Sqs148142 dma_p->dma_handle = NULL; 23236349Sqs148142 dma_p->acc_handle = NULL; 23246349Sqs148142 dma_p->kaddrp = NULL; 23256349Sqs148142 23266349Sqs148142 ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp, 23276349Sqs148142 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 23286349Sqs148142 if (ddi_status != DDI_SUCCESS) { 23296349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23306349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 23316349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 23326349Sqs148142 } 23336349Sqs148142 23346349Sqs148142 ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p, 23356349Sqs148142 xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 23366349Sqs148142 &dma_p->acc_handle); 23376349Sqs148142 if (ddi_status != DDI_SUCCESS) { 23386349Sqs148142 /* The caller will decide whether it is fatal */ 23396349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 23406349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 23416349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle); 23426349Sqs148142 dma_p->dma_handle = NULL; 23436349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 23446349Sqs148142 } 23456349Sqs148142 23466349Sqs148142 if (dma_p->alength < length) { 23476349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23486349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length.")); 23496349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle); 23506349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle); 23516349Sqs148142 dma_p->acc_handle = NULL; 23526349Sqs148142 dma_p->dma_handle = NULL; 23536349Sqs148142 return (HXGE_ERROR); 23546349Sqs148142 } 23556349Sqs148142 23566349Sqs148142 ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 23576349Sqs148142 kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 23586349Sqs148142 &dma_p->dma_cookie, &dma_p->ncookies); 23596349Sqs148142 if (ddi_status != DDI_DMA_MAPPED) { 23606349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23616349Sqs148142 "hxge_dma_mem_alloc:di_dma_addr_bind failed " 23626349Sqs148142 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 23636349Sqs148142 if (dma_p->acc_handle) { 23646349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle); 23656349Sqs148142 dma_p->acc_handle = NULL; 23666349Sqs148142 } 23676349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle); 23686349Sqs148142 dma_p->dma_handle = NULL; 23696349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 23706349Sqs148142 } 23716349Sqs148142 23726349Sqs148142 if (dma_p->ncookies != 1) { 23736349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 23746349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie" 23756349Sqs148142 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 23766349Sqs148142 if (dma_p->acc_handle) { 23776349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle); 23786349Sqs148142 dma_p->acc_handle = NULL; 23796349Sqs148142 } 23806349Sqs148142 (void) ddi_dma_unbind_handle(dma_p->dma_handle); 23816349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle); 23826349Sqs148142 dma_p->dma_handle = NULL; 23836349Sqs148142 return (HXGE_ERROR); 23846349Sqs148142 } 23856349Sqs148142 23866349Sqs148142 dma_p->kaddrp = kaddrp; 23876349Sqs148142 #if defined(__i386) 23886349Sqs148142 dma_p->ioaddr_pp = 23896349Sqs148142 (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 23906349Sqs148142 #else 23916349Sqs148142 dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress; 23926349Sqs148142 #endif 23936349Sqs148142 23946349Sqs148142 HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 23956349Sqs148142 23966349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: " 23976349Sqs148142 "dma buffer allocated: dma_p $%p " 23986349Sqs148142 "return dmac_ladress from cookie $%p dmac_size %d " 23996349Sqs148142 "dma_p->ioaddr_p $%p " 24006349Sqs148142 "dma_p->orig_ioaddr_p $%p " 24016349Sqs148142 "orig_vatopa $%p " 24026349Sqs148142 "alength %d (0x%x) " 24036349Sqs148142 "kaddrp $%p " 24046349Sqs148142 "length %d (0x%x)", 24056349Sqs148142 dma_p, 24066349Sqs148142 dma_p->dma_cookie.dmac_laddress, 24076349Sqs148142 dma_p->dma_cookie.dmac_size, 24086349Sqs148142 dma_p->ioaddr_pp, 24096349Sqs148142 dma_p->orig_ioaddr_pp, 24106349Sqs148142 dma_p->orig_vatopa, 24116349Sqs148142 dma_p->alength, dma_p->alength, 24126349Sqs148142 kaddrp, 24136349Sqs148142 length, length)); 24146349Sqs148142 24156349Sqs148142 return (HXGE_OK); 24166349Sqs148142 } 24176349Sqs148142 24186349Sqs148142 static void 24196349Sqs148142 hxge_dma_mem_free(p_hxge_dma_common_t dma_p) 24206349Sqs148142 { 24217618SMichael.Speer@Sun.COM if (dma_p == NULL) 24227618SMichael.Speer@Sun.COM return; 24237618SMichael.Speer@Sun.COM 24246349Sqs148142 if (dma_p->dma_handle != NULL) { 24256349Sqs148142 if (dma_p->ncookies) { 24266349Sqs148142 (void) ddi_dma_unbind_handle(dma_p->dma_handle); 24276349Sqs148142 dma_p->ncookies = 0; 24286349Sqs148142 } 24296349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle); 24306349Sqs148142 dma_p->dma_handle = NULL; 24316349Sqs148142 } 24327618SMichael.Speer@Sun.COM 24336349Sqs148142 if (dma_p->acc_handle != NULL) { 24346349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle); 24356349Sqs148142 dma_p->acc_handle = NULL; 24366349Sqs148142 HPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 24376349Sqs148142 } 24387618SMichael.Speer@Sun.COM 24396349Sqs148142 dma_p->kaddrp = NULL; 24406349Sqs148142 dma_p->alength = NULL; 24416349Sqs148142 } 24426349Sqs148142 24436349Sqs148142 /* 24446349Sqs148142 * hxge_m_start() -- start transmitting and receiving. 24456349Sqs148142 * 24466349Sqs148142 * This function is called by the MAC layer when the first 24476349Sqs148142 * stream is open to prepare the hardware ready for sending 24486349Sqs148142 * and transmitting packets. 24496349Sqs148142 */ 24506349Sqs148142 static int 24516349Sqs148142 hxge_m_start(void *arg) 24526349Sqs148142 { 24536349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 24546349Sqs148142 24556349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start")); 24566349Sqs148142 24576349Sqs148142 MUTEX_ENTER(hxgep->genlock); 24586349Sqs148142 24596349Sqs148142 if (hxge_init(hxgep) != DDI_SUCCESS) { 24606349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24616349Sqs148142 "<== hxge_m_start: initialization failed")); 24626349Sqs148142 MUTEX_EXIT(hxgep->genlock); 24636349Sqs148142 return (EIO); 24646349Sqs148142 } 24656349Sqs148142 24666349Sqs148142 if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) { 24676349Sqs148142 /* 24686349Sqs148142 * Start timer to check the system error and tx hangs 24696349Sqs148142 */ 24706349Sqs148142 hxgep->hxge_timerid = hxge_start_timer(hxgep, 24716349Sqs148142 hxge_check_hw_state, HXGE_CHECK_TIMER); 24726349Sqs148142 24736349Sqs148142 hxgep->hxge_mac_state = HXGE_MAC_STARTED; 24746349Sqs148142 } 24756349Sqs148142 24766349Sqs148142 MUTEX_EXIT(hxgep->genlock); 24776349Sqs148142 24786349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start")); 24796349Sqs148142 24806349Sqs148142 return (0); 24816349Sqs148142 } 24826349Sqs148142 24836349Sqs148142 /* 24846349Sqs148142 * hxge_m_stop(): stop transmitting and receiving. 24856349Sqs148142 */ 24866349Sqs148142 static void 24876349Sqs148142 hxge_m_stop(void *arg) 24886349Sqs148142 { 24896349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 24906349Sqs148142 24916349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop")); 24926349Sqs148142 24936349Sqs148142 if (hxgep->hxge_timerid) { 24946349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 24956349Sqs148142 hxgep->hxge_timerid = 0; 24966349Sqs148142 } 24976349Sqs148142 24986349Sqs148142 MUTEX_ENTER(hxgep->genlock); 24996349Sqs148142 25006349Sqs148142 hxge_uninit(hxgep); 25016349Sqs148142 25026349Sqs148142 hxgep->hxge_mac_state = HXGE_MAC_STOPPED; 25036349Sqs148142 25046349Sqs148142 MUTEX_EXIT(hxgep->genlock); 25056349Sqs148142 25066349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop")); 25076349Sqs148142 } 25086349Sqs148142 25096349Sqs148142 static int 25106349Sqs148142 hxge_m_unicst(void *arg, const uint8_t *macaddr) 25116349Sqs148142 { 25126349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 25136349Sqs148142 struct ether_addr addrp; 25146349Sqs148142 hxge_status_t status; 25156349Sqs148142 25166349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_unicst")); 25176349Sqs148142 25186349Sqs148142 bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 25196349Sqs148142 25206349Sqs148142 status = hxge_set_mac_addr(hxgep, &addrp); 25216349Sqs148142 if (status != HXGE_OK) { 25226349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25236349Sqs148142 "<== hxge_m_unicst: set unitcast failed")); 25246349Sqs148142 return (EINVAL); 25256349Sqs148142 } 25266349Sqs148142 25276349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_unicst")); 25286349Sqs148142 25296349Sqs148142 return (0); 25306349Sqs148142 } 25316349Sqs148142 25326349Sqs148142 static int 25336349Sqs148142 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 25346349Sqs148142 { 25356349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 25366349Sqs148142 struct ether_addr addrp; 25376349Sqs148142 25386349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add)); 25396349Sqs148142 25406349Sqs148142 bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 25416349Sqs148142 25426349Sqs148142 if (add) { 25436349Sqs148142 if (hxge_add_mcast_addr(hxgep, &addrp)) { 25446349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25456349Sqs148142 "<== hxge_m_multicst: add multicast failed")); 25466349Sqs148142 return (EINVAL); 25476349Sqs148142 } 25486349Sqs148142 } else { 25496349Sqs148142 if (hxge_del_mcast_addr(hxgep, &addrp)) { 25506349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25516349Sqs148142 "<== hxge_m_multicst: del multicast failed")); 25526349Sqs148142 return (EINVAL); 25536349Sqs148142 } 25546349Sqs148142 } 25556349Sqs148142 25566349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst")); 25576349Sqs148142 25586349Sqs148142 return (0); 25596349Sqs148142 } 25606349Sqs148142 25616349Sqs148142 static int 25626349Sqs148142 hxge_m_promisc(void *arg, boolean_t on) 25636349Sqs148142 { 25646349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 25656349Sqs148142 25666349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on)); 25676349Sqs148142 25686349Sqs148142 if (hxge_set_promisc(hxgep, on)) { 25696349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25706349Sqs148142 "<== hxge_m_promisc: set promisc failed")); 25716349Sqs148142 return (EINVAL); 25726349Sqs148142 } 25736349Sqs148142 25746349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on)); 25756349Sqs148142 25766349Sqs148142 return (0); 25776349Sqs148142 } 25786349Sqs148142 25796349Sqs148142 static void 25806349Sqs148142 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 25816349Sqs148142 { 25826349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 25836349Sqs148142 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 25846349Sqs148142 boolean_t need_privilege; 25856349Sqs148142 int err; 25866349Sqs148142 int cmd; 25876349Sqs148142 25886349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl")); 25896349Sqs148142 25906349Sqs148142 iocp = (struct iocblk *)mp->b_rptr; 25916349Sqs148142 iocp->ioc_error = 0; 25926349Sqs148142 need_privilege = B_TRUE; 25936349Sqs148142 cmd = iocp->ioc_cmd; 25946349Sqs148142 25956349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd)); 25966349Sqs148142 switch (cmd) { 25976349Sqs148142 default: 25986349Sqs148142 miocnak(wq, mp, 0, EINVAL); 25996349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid")); 26006349Sqs148142 return; 26016349Sqs148142 26026349Sqs148142 case LB_GET_INFO_SIZE: 26036349Sqs148142 case LB_GET_INFO: 26046349Sqs148142 case LB_GET_MODE: 26056349Sqs148142 need_privilege = B_FALSE; 26066349Sqs148142 break; 26076349Sqs148142 26086349Sqs148142 case LB_SET_MODE: 26096349Sqs148142 break; 26106349Sqs148142 26116349Sqs148142 case ND_GET: 26126349Sqs148142 need_privilege = B_FALSE; 26136349Sqs148142 break; 26146349Sqs148142 case ND_SET: 26156349Sqs148142 break; 26166349Sqs148142 26176349Sqs148142 case HXGE_GET64: 26186349Sqs148142 case HXGE_PUT64: 26196349Sqs148142 case HXGE_GET_TX_RING_SZ: 26206349Sqs148142 case HXGE_GET_TX_DESC: 26216349Sqs148142 case HXGE_TX_SIDE_RESET: 26226349Sqs148142 case HXGE_RX_SIDE_RESET: 26236349Sqs148142 case HXGE_GLOBAL_RESET: 26246349Sqs148142 case HXGE_RESET_MAC: 26256349Sqs148142 case HXGE_PUT_TCAM: 26266349Sqs148142 case HXGE_GET_TCAM: 26276349Sqs148142 case HXGE_RTRACE: 26286349Sqs148142 26296349Sqs148142 need_privilege = B_FALSE; 26306349Sqs148142 break; 26316349Sqs148142 } 26326349Sqs148142 26336349Sqs148142 if (need_privilege) { 26346349Sqs148142 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 26356349Sqs148142 if (err != 0) { 26366349Sqs148142 miocnak(wq, mp, 0, err); 26376349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 26386349Sqs148142 "<== hxge_m_ioctl: no priv")); 26396349Sqs148142 return; 26406349Sqs148142 } 26416349Sqs148142 } 26426349Sqs148142 26436349Sqs148142 switch (cmd) { 26446349Sqs148142 case ND_GET: 26456349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command")); 26466349Sqs148142 case ND_SET: 26476349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command")); 26486349Sqs148142 hxge_param_ioctl(hxgep, wq, mp, iocp); 26496349Sqs148142 break; 26506349Sqs148142 26516349Sqs148142 case LB_GET_MODE: 26526349Sqs148142 case LB_SET_MODE: 26536349Sqs148142 case LB_GET_INFO_SIZE: 26546349Sqs148142 case LB_GET_INFO: 26556349Sqs148142 hxge_loopback_ioctl(hxgep, wq, mp, iocp); 26566349Sqs148142 break; 26576349Sqs148142 26586349Sqs148142 case HXGE_PUT_TCAM: 26596349Sqs148142 case HXGE_GET_TCAM: 26606349Sqs148142 case HXGE_GET64: 26616349Sqs148142 case HXGE_PUT64: 26626349Sqs148142 case HXGE_GET_TX_RING_SZ: 26636349Sqs148142 case HXGE_GET_TX_DESC: 26646349Sqs148142 case HXGE_TX_SIDE_RESET: 26656349Sqs148142 case HXGE_RX_SIDE_RESET: 26666349Sqs148142 case HXGE_GLOBAL_RESET: 26676349Sqs148142 case HXGE_RESET_MAC: 26686349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, 26696349Sqs148142 "==> hxge_m_ioctl: cmd 0x%x", cmd)); 26706349Sqs148142 hxge_hw_ioctl(hxgep, wq, mp, iocp); 26716349Sqs148142 break; 26726349Sqs148142 } 26736349Sqs148142 26746349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl")); 26756349Sqs148142 } 26766349Sqs148142 26776349Sqs148142 extern void hxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 26786349Sqs148142 26796349Sqs148142 static void 26806349Sqs148142 hxge_m_resources(void *arg) 26816349Sqs148142 { 26826349Sqs148142 p_hxge_t hxgep = arg; 26836349Sqs148142 mac_rx_fifo_t mrf; 26846349Sqs148142 p_rx_rcr_rings_t rcr_rings; 26856349Sqs148142 p_rx_rcr_ring_t *rcr_p; 26866349Sqs148142 p_rx_rcr_ring_t rcrp; 26876349Sqs148142 uint32_t i, ndmas; 26886349Sqs148142 int status; 26896349Sqs148142 26906349Sqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources")); 26916349Sqs148142 26926349Sqs148142 MUTEX_ENTER(hxgep->genlock); 26936349Sqs148142 26946349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 26956349Sqs148142 status = hxge_init(hxgep); 26966349Sqs148142 if (status != HXGE_OK) { 26976349Sqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources: " 26986349Sqs148142 "hxge_init failed")); 26996349Sqs148142 MUTEX_EXIT(hxgep->genlock); 27006349Sqs148142 return; 27016349Sqs148142 } 27026349Sqs148142 } 27036349Sqs148142 27046349Sqs148142 mrf.mrf_type = MAC_RX_FIFO; 27056349Sqs148142 mrf.mrf_blank = hxge_rx_hw_blank; 27066864Sqs148142 mrf.mrf_arg = (void *)hxgep; 27076864Sqs148142 27086864Sqs148142 mrf.mrf_normal_blank_time = RXDMA_RCR_TO_DEFAULT; 27096864Sqs148142 mrf.mrf_normal_pkt_count = RXDMA_RCR_PTHRES_DEFAULT; 27106349Sqs148142 27116349Sqs148142 rcr_rings = hxgep->rx_rcr_rings; 27126349Sqs148142 rcr_p = rcr_rings->rcr_rings; 27136349Sqs148142 ndmas = rcr_rings->ndmas; 27146349Sqs148142 27156349Sqs148142 /* 27166349Sqs148142 * Export our receive resources to the MAC layer. 27176349Sqs148142 */ 27186349Sqs148142 for (i = 0; i < ndmas; i++) { 27196349Sqs148142 rcrp = (void *)(p_rx_rcr_ring_t)rcr_p[i]; 27206349Sqs148142 rcrp->rcr_mac_handle = 27216349Sqs148142 mac_resource_add(hxgep->mach, (mac_resource_t *)&mrf); 27226349Sqs148142 27236349Sqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 27246349Sqs148142 "==> hxge_m_resources: vdma %d dma %d " 27256349Sqs148142 "rcrptr 0x%016llx mac_handle 0x%016llx", 27266349Sqs148142 i, rcrp->rdc, rcr_p[i], rcrp->rcr_mac_handle)); 27276349Sqs148142 } 27286349Sqs148142 27296349Sqs148142 MUTEX_EXIT(hxgep->genlock); 27306349Sqs148142 27316349Sqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_m_resources")); 27326349Sqs148142 } 27336349Sqs148142 27346349Sqs148142 /* 27356349Sqs148142 * Set an alternate MAC address 27366349Sqs148142 */ 27376349Sqs148142 static int 27386349Sqs148142 hxge_altmac_set(p_hxge_t hxgep, uint8_t *maddr, mac_addr_slot_t slot) 27396349Sqs148142 { 27406349Sqs148142 uint64_t address; 27416349Sqs148142 uint64_t tmp; 27426349Sqs148142 hpi_status_t status; 27436349Sqs148142 uint8_t addrn; 27446349Sqs148142 int i; 27456349Sqs148142 27466349Sqs148142 /* 27476349Sqs148142 * Convert a byte array to a 48 bit value. 27486349Sqs148142 * Need to check endianess if in doubt 27496349Sqs148142 */ 27506349Sqs148142 address = 0; 27516349Sqs148142 for (i = 0; i < ETHERADDRL; i++) { 27526349Sqs148142 tmp = maddr[i]; 27536349Sqs148142 address <<= 8; 27546349Sqs148142 address |= tmp; 27556349Sqs148142 } 27566349Sqs148142 27576349Sqs148142 addrn = (uint8_t)slot; 27586349Sqs148142 status = hpi_pfc_set_mac_address(hxgep->hpi_handle, addrn, address); 27596349Sqs148142 if (status != HPI_SUCCESS) 27606349Sqs148142 return (EIO); 27616349Sqs148142 27626349Sqs148142 return (0); 27636349Sqs148142 } 27646349Sqs148142 27656349Sqs148142 static void 27666349Sqs148142 hxge_mmac_kstat_update(p_hxge_t hxgep, mac_addr_slot_t slot) 27676349Sqs148142 { 27686349Sqs148142 p_hxge_mmac_stats_t mmac_stats; 27696349Sqs148142 int i; 27706349Sqs148142 hxge_mmac_t *mmac_info; 27716349Sqs148142 27726349Sqs148142 mmac_info = &hxgep->hxge_mmac_info; 27736349Sqs148142 mmac_stats = &hxgep->statsp->mmac_stats; 27746349Sqs148142 mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 27756349Sqs148142 mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 27766349Sqs148142 27776349Sqs148142 for (i = 0; i < ETHERADDRL; i++) { 27786349Sqs148142 mmac_stats->mmac_avail_pool[slot].ether_addr_octet[i] = 27796349Sqs148142 mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i]; 27806349Sqs148142 } 27816349Sqs148142 } 27826349Sqs148142 27836349Sqs148142 /* 27846349Sqs148142 * Find an unused address slot, set the address value to the one specified, 27856349Sqs148142 * enable the port to start filtering on the new MAC address. 27866349Sqs148142 * Returns: 0 on success. 27876349Sqs148142 */ 27886349Sqs148142 int 27896349Sqs148142 hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 27906349Sqs148142 { 27916349Sqs148142 p_hxge_t hxgep = arg; 27926349Sqs148142 mac_addr_slot_t slot; 27936349Sqs148142 hxge_mmac_t *mmac_info; 27946349Sqs148142 int err; 27956349Sqs148142 hxge_status_t status; 27966349Sqs148142 27976349Sqs148142 mutex_enter(hxgep->genlock); 27986349Sqs148142 27996349Sqs148142 /* 28006349Sqs148142 * Make sure that hxge is initialized, if _start() has 28016349Sqs148142 * not been called. 28026349Sqs148142 */ 28036349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 28046349Sqs148142 status = hxge_init(hxgep); 28056349Sqs148142 if (status != HXGE_OK) { 28066349Sqs148142 mutex_exit(hxgep->genlock); 28076349Sqs148142 return (ENXIO); 28086349Sqs148142 } 28096349Sqs148142 } 28106349Sqs148142 28116349Sqs148142 mmac_info = &hxgep->hxge_mmac_info; 28126349Sqs148142 if (mmac_info->naddrfree == 0) { 28136349Sqs148142 mutex_exit(hxgep->genlock); 28146349Sqs148142 return (ENOSPC); 28156349Sqs148142 } 28166349Sqs148142 28176349Sqs148142 if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr, 28186349Sqs148142 maddr->mma_addrlen)) { 28196349Sqs148142 mutex_exit(hxgep->genlock); 28206349Sqs148142 return (EINVAL); 28216349Sqs148142 } 28226349Sqs148142 28236349Sqs148142 /* 28246349Sqs148142 * Search for the first available slot. Because naddrfree 28256349Sqs148142 * is not zero, we are guaranteed to find one. 28266349Sqs148142 * Slot 0 is for unique (primary) MAC. The first alternate 28276349Sqs148142 * MAC slot is slot 1. 28286349Sqs148142 */ 28296349Sqs148142 for (slot = 1; slot < mmac_info->num_mmac; slot++) { 28306349Sqs148142 if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 28316349Sqs148142 break; 28326349Sqs148142 } 28336349Sqs148142 28346349Sqs148142 ASSERT(slot < mmac_info->num_mmac); 28356349Sqs148142 if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, slot)) != 0) { 28366349Sqs148142 mutex_exit(hxgep->genlock); 28376349Sqs148142 return (err); 28386349Sqs148142 } 28396349Sqs148142 bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 28406349Sqs148142 mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 28416349Sqs148142 mmac_info->naddrfree--; 28426349Sqs148142 hxge_mmac_kstat_update(hxgep, slot); 28436349Sqs148142 28446349Sqs148142 maddr->mma_slot = slot; 28456349Sqs148142 28466349Sqs148142 mutex_exit(hxgep->genlock); 28476349Sqs148142 return (0); 28486349Sqs148142 } 28496349Sqs148142 28506349Sqs148142 /* 28516349Sqs148142 * Remove the specified mac address and update 28526349Sqs148142 * the h/w not to filter the mac address anymore. 28536349Sqs148142 * Returns: 0, on success. 28546349Sqs148142 */ 28556349Sqs148142 int 28566349Sqs148142 hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 28576349Sqs148142 { 28586349Sqs148142 p_hxge_t hxgep = arg; 28596349Sqs148142 hxge_mmac_t *mmac_info; 28606349Sqs148142 int err = 0; 28616349Sqs148142 hxge_status_t status; 28626349Sqs148142 28636349Sqs148142 mutex_enter(hxgep->genlock); 28646349Sqs148142 28656349Sqs148142 /* 28666349Sqs148142 * Make sure that hxge is initialized, if _start() has 28676349Sqs148142 * not been called. 28686349Sqs148142 */ 28696349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 28706349Sqs148142 status = hxge_init(hxgep); 28716349Sqs148142 if (status != HXGE_OK) { 28726349Sqs148142 mutex_exit(hxgep->genlock); 28736349Sqs148142 return (ENXIO); 28746349Sqs148142 } 28756349Sqs148142 } 28766349Sqs148142 28776349Sqs148142 mmac_info = &hxgep->hxge_mmac_info; 28786349Sqs148142 if (slot <= 0 || slot >= mmac_info->num_mmac) { 28796349Sqs148142 mutex_exit(hxgep->genlock); 28806349Sqs148142 return (EINVAL); 28816349Sqs148142 } 28826349Sqs148142 28836349Sqs148142 if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 28846349Sqs148142 if (hpi_pfc_mac_addr_disable(hxgep->hpi_handle, slot) == 28856349Sqs148142 HPI_SUCCESS) { 28866349Sqs148142 mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 28876349Sqs148142 mmac_info->naddrfree++; 28886349Sqs148142 /* 28896349Sqs148142 * Clear mac_pool[slot].addr so that kstat shows 0 28906349Sqs148142 * alternate MAC address if the slot is not used. 28916349Sqs148142 */ 28926349Sqs148142 bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 28936349Sqs148142 hxge_mmac_kstat_update(hxgep, slot); 28946349Sqs148142 } else { 28956349Sqs148142 err = EIO; 28966349Sqs148142 } 28976349Sqs148142 } else { 28986349Sqs148142 err = EINVAL; 28996349Sqs148142 } 29006349Sqs148142 29016349Sqs148142 mutex_exit(hxgep->genlock); 29026349Sqs148142 return (err); 29036349Sqs148142 } 29046349Sqs148142 29056349Sqs148142 /* 29066349Sqs148142 * Modify a mac address added by hxge_mmac_add(). 29076349Sqs148142 * Returns: 0, on success. 29086349Sqs148142 */ 29096349Sqs148142 int 29106349Sqs148142 hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 29116349Sqs148142 { 29126349Sqs148142 p_hxge_t hxgep = arg; 29136349Sqs148142 mac_addr_slot_t slot; 29146349Sqs148142 hxge_mmac_t *mmac_info; 29156349Sqs148142 int err = 0; 29166349Sqs148142 hxge_status_t status; 29176349Sqs148142 29186349Sqs148142 if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr, 29196349Sqs148142 maddr->mma_addrlen)) 29206349Sqs148142 return (EINVAL); 29216349Sqs148142 29226349Sqs148142 slot = maddr->mma_slot; 29236349Sqs148142 29246349Sqs148142 mutex_enter(hxgep->genlock); 29256349Sqs148142 29266349Sqs148142 /* 29276349Sqs148142 * Make sure that hxge is initialized, if _start() has 29286349Sqs148142 * not been called. 29296349Sqs148142 */ 29306349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 29316349Sqs148142 status = hxge_init(hxgep); 29326349Sqs148142 if (status != HXGE_OK) { 29336349Sqs148142 mutex_exit(hxgep->genlock); 29346349Sqs148142 return (ENXIO); 29356349Sqs148142 } 29366349Sqs148142 } 29376349Sqs148142 29386349Sqs148142 mmac_info = &hxgep->hxge_mmac_info; 29396349Sqs148142 if (slot <= 0 || slot >= mmac_info->num_mmac) { 29406349Sqs148142 mutex_exit(hxgep->genlock); 29416349Sqs148142 return (EINVAL); 29426349Sqs148142 } 29436349Sqs148142 29446349Sqs148142 if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 29456349Sqs148142 if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, 29466349Sqs148142 slot)) == 0) { 29476349Sqs148142 bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 29486349Sqs148142 ETHERADDRL); 29496349Sqs148142 hxge_mmac_kstat_update(hxgep, slot); 29506349Sqs148142 } 29516349Sqs148142 } else { 29526349Sqs148142 err = EINVAL; 29536349Sqs148142 } 29546349Sqs148142 29556349Sqs148142 mutex_exit(hxgep->genlock); 29566349Sqs148142 return (err); 29576349Sqs148142 } 29586349Sqs148142 29596349Sqs148142 /* 29606349Sqs148142 * static int 29616349Sqs148142 * hxge_m_mmac_get() - Get the MAC address and other information 29626349Sqs148142 * related to the slot. mma_flags should be set to 0 in the call. 29636349Sqs148142 * Note: although kstat shows MAC address as zero when a slot is 29646349Sqs148142 * not used, Crossbow expects hxge_m_mmac_get to copy factory MAC 29656349Sqs148142 * to the caller as long as the slot is not using a user MAC address. 29666349Sqs148142 * The following table shows the rules, 29676349Sqs148142 * 29686349Sqs148142 * USED VENDOR mma_addr 29696349Sqs148142 * ------------------------------------------------------------ 29706349Sqs148142 * (1) Slot uses a user MAC: yes no user MAC 29716349Sqs148142 * (2) Slot uses a factory MAC: yes yes factory MAC 29726349Sqs148142 * (3) Slot is not used but is 29736349Sqs148142 * factory MAC capable: no yes factory MAC 29746349Sqs148142 * (4) Slot is not used and is 29756349Sqs148142 * not factory MAC capable: no no 0 29766349Sqs148142 * ------------------------------------------------------------ 29776349Sqs148142 */ 29786349Sqs148142 int 29796349Sqs148142 hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 29806349Sqs148142 { 29816349Sqs148142 hxge_t *hxgep = arg; 29826349Sqs148142 mac_addr_slot_t slot; 29836349Sqs148142 hxge_mmac_t *mmac_info; 29846349Sqs148142 hxge_status_t status; 29856349Sqs148142 29866349Sqs148142 slot = maddr->mma_slot; 29876349Sqs148142 29886349Sqs148142 mutex_enter(hxgep->genlock); 29896349Sqs148142 29906349Sqs148142 /* 29916349Sqs148142 * Make sure that hxge is initialized, if _start() has 29926349Sqs148142 * not been called. 29936349Sqs148142 */ 29946349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 29956349Sqs148142 status = hxge_init(hxgep); 29966349Sqs148142 if (status != HXGE_OK) { 29976349Sqs148142 mutex_exit(hxgep->genlock); 29986349Sqs148142 return (ENXIO); 29996349Sqs148142 } 30006349Sqs148142 } 30016349Sqs148142 30026349Sqs148142 mmac_info = &hxgep->hxge_mmac_info; 30036349Sqs148142 if (slot <= 0 || slot >= mmac_info->num_mmac) { 30046349Sqs148142 mutex_exit(hxgep->genlock); 30056349Sqs148142 return (EINVAL); 30066349Sqs148142 } 30076349Sqs148142 30086349Sqs148142 maddr->mma_flags = 0; 30096349Sqs148142 if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 30106349Sqs148142 maddr->mma_flags |= MMAC_SLOT_USED; 30116349Sqs148142 bcopy(mmac_info->mac_pool[slot].addr, 30126349Sqs148142 maddr->mma_addr, ETHERADDRL); 30136349Sqs148142 maddr->mma_addrlen = ETHERADDRL; 30146349Sqs148142 } 30156349Sqs148142 30166349Sqs148142 mutex_exit(hxgep->genlock); 30176349Sqs148142 return (0); 30186349Sqs148142 } 30196349Sqs148142 30206349Sqs148142 /*ARGSUSED*/ 30216349Sqs148142 boolean_t 30226349Sqs148142 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 30236349Sqs148142 { 30246349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg; 30256349Sqs148142 uint32_t *txflags = cap_data; 30266349Sqs148142 multiaddress_capab_t *mmacp = cap_data; 30276349Sqs148142 30286349Sqs148142 switch (cap) { 30296349Sqs148142 case MAC_CAPAB_HCKSUM: 30306349Sqs148142 *txflags = HCKSUM_INET_PARTIAL; 30316349Sqs148142 break; 30326349Sqs148142 30336349Sqs148142 case MAC_CAPAB_POLL: 30346349Sqs148142 /* 30356349Sqs148142 * There's nothing for us to fill in, simply returning B_TRUE 30366349Sqs148142 * stating that we support polling is sufficient. 30376349Sqs148142 */ 30386349Sqs148142 break; 30396349Sqs148142 30406349Sqs148142 case MAC_CAPAB_MULTIADDRESS: 30416349Sqs148142 /* 30426349Sqs148142 * The number of MAC addresses made available by 30436349Sqs148142 * this capability is one less than the total as 30446349Sqs148142 * the primary address in slot 0 is counted in 30456349Sqs148142 * the total. 30466349Sqs148142 */ 30476349Sqs148142 mmacp->maddr_naddr = PFC_N_MAC_ADDRESSES - 1; 30486349Sqs148142 mmacp->maddr_naddrfree = hxgep->hxge_mmac_info.naddrfree; 30496349Sqs148142 mmacp->maddr_flag = 0; /* No multiple factory macs */ 30506349Sqs148142 mmacp->maddr_handle = hxgep; 30516349Sqs148142 mmacp->maddr_add = hxge_m_mmac_add; 30526349Sqs148142 mmacp->maddr_remove = hxge_m_mmac_remove; 30536349Sqs148142 mmacp->maddr_modify = hxge_m_mmac_modify; 30546349Sqs148142 mmacp->maddr_get = hxge_m_mmac_get; 30556349Sqs148142 mmacp->maddr_reserve = NULL; /* No multiple factory macs */ 30566349Sqs148142 break; 30576349Sqs148142 default: 30586349Sqs148142 return (B_FALSE); 30596349Sqs148142 } 30606349Sqs148142 return (B_TRUE); 30616349Sqs148142 } 30626349Sqs148142 30637584SQiyan.Sun@Sun.COM static boolean_t 30647584SQiyan.Sun@Sun.COM hxge_param_locked(mac_prop_id_t pr_num) 30657584SQiyan.Sun@Sun.COM { 30667584SQiyan.Sun@Sun.COM /* 30677584SQiyan.Sun@Sun.COM * All adv_* parameters are locked (read-only) while 30687584SQiyan.Sun@Sun.COM * the device is in any sort of loopback mode ... 30697584SQiyan.Sun@Sun.COM */ 30707584SQiyan.Sun@Sun.COM switch (pr_num) { 30717584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 30727584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 30737584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 30747584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 30757584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 30767584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP: 30777584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 30787584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP: 30797584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 30807584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP: 30817584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 30827584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP: 30837584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG: 30847584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL: 30857584SQiyan.Sun@Sun.COM return (B_TRUE); 30867584SQiyan.Sun@Sun.COM } 30877584SQiyan.Sun@Sun.COM return (B_FALSE); 30887584SQiyan.Sun@Sun.COM } 30897584SQiyan.Sun@Sun.COM 30907584SQiyan.Sun@Sun.COM /* 30917584SQiyan.Sun@Sun.COM * callback functions for set/get of properties 30927584SQiyan.Sun@Sun.COM */ 30937584SQiyan.Sun@Sun.COM static int 30947584SQiyan.Sun@Sun.COM hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 30957584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val) 30967584SQiyan.Sun@Sun.COM { 30977584SQiyan.Sun@Sun.COM hxge_t *hxgep = barg; 30987584SQiyan.Sun@Sun.COM p_hxge_stats_t statsp; 30997584SQiyan.Sun@Sun.COM int err = 0; 31007584SQiyan.Sun@Sun.COM uint32_t new_mtu, old_framesize, new_framesize; 31017584SQiyan.Sun@Sun.COM 31027584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop")); 31037584SQiyan.Sun@Sun.COM 31047584SQiyan.Sun@Sun.COM statsp = hxgep->statsp; 31057584SQiyan.Sun@Sun.COM mutex_enter(hxgep->genlock); 31067584SQiyan.Sun@Sun.COM if (statsp->port_stats.lb_mode != hxge_lb_normal && 31077584SQiyan.Sun@Sun.COM hxge_param_locked(pr_num)) { 31087584SQiyan.Sun@Sun.COM /* 31097584SQiyan.Sun@Sun.COM * All adv_* parameters are locked (read-only) 31107584SQiyan.Sun@Sun.COM * while the device is in any sort of loopback mode. 31117584SQiyan.Sun@Sun.COM */ 31127584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 31137584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: loopback mode: read only")); 31147584SQiyan.Sun@Sun.COM mutex_exit(hxgep->genlock); 31157584SQiyan.Sun@Sun.COM return (EBUSY); 31167584SQiyan.Sun@Sun.COM } 31177584SQiyan.Sun@Sun.COM 31187584SQiyan.Sun@Sun.COM switch (pr_num) { 31197584SQiyan.Sun@Sun.COM /* 31207584SQiyan.Sun@Sun.COM * These properties are either not exist or read only 31217584SQiyan.Sun@Sun.COM */ 31227584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 31237584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP: 31247584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP: 31257584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 31267584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP: 31277584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP: 31287584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 31297584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 31307584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 31317584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 31327584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 31337584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 31347584SQiyan.Sun@Sun.COM case MAC_PROP_STATUS: 31357584SQiyan.Sun@Sun.COM case MAC_PROP_SPEED: 31367584SQiyan.Sun@Sun.COM case MAC_PROP_DUPLEX: 31377584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG: 31387584SQiyan.Sun@Sun.COM /* 31397584SQiyan.Sun@Sun.COM * Flow control is handled in the shared domain and 31407584SQiyan.Sun@Sun.COM * it is readonly here. 31417584SQiyan.Sun@Sun.COM */ 31427584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL: 31437584SQiyan.Sun@Sun.COM err = EINVAL; 31447584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 31457584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: read only property %d", 31467584SQiyan.Sun@Sun.COM pr_num)); 31477584SQiyan.Sun@Sun.COM break; 31487584SQiyan.Sun@Sun.COM 31497584SQiyan.Sun@Sun.COM case MAC_PROP_MTU: 31507584SQiyan.Sun@Sun.COM if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) { 31517584SQiyan.Sun@Sun.COM err = EBUSY; 31527584SQiyan.Sun@Sun.COM break; 31537584SQiyan.Sun@Sun.COM } 31547584SQiyan.Sun@Sun.COM 31557584SQiyan.Sun@Sun.COM bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 31567584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 31577584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: set MTU: %d", new_mtu)); 31587584SQiyan.Sun@Sun.COM 31597584SQiyan.Sun@Sun.COM new_framesize = new_mtu + MTU_TO_FRAME_SIZE; 31607584SQiyan.Sun@Sun.COM if (new_framesize == hxgep->vmac.maxframesize) { 31617584SQiyan.Sun@Sun.COM err = 0; 31627584SQiyan.Sun@Sun.COM break; 31637584SQiyan.Sun@Sun.COM } 31647584SQiyan.Sun@Sun.COM 31657584SQiyan.Sun@Sun.COM if (new_framesize < MIN_FRAME_SIZE || 31667584SQiyan.Sun@Sun.COM new_framesize > MAX_FRAME_SIZE) { 31677584SQiyan.Sun@Sun.COM err = EINVAL; 31687584SQiyan.Sun@Sun.COM break; 31697584SQiyan.Sun@Sun.COM } 31707584SQiyan.Sun@Sun.COM 31717584SQiyan.Sun@Sun.COM old_framesize = hxgep->vmac.maxframesize; 31727584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize = (uint16_t)new_framesize; 31737584SQiyan.Sun@Sun.COM 31747584SQiyan.Sun@Sun.COM if (hxge_vmac_set_framesize(hxgep)) { 31757584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize = 31767584SQiyan.Sun@Sun.COM (uint16_t)old_framesize; 31777584SQiyan.Sun@Sun.COM err = EINVAL; 31787584SQiyan.Sun@Sun.COM break; 31797584SQiyan.Sun@Sun.COM } 31807584SQiyan.Sun@Sun.COM 31817584SQiyan.Sun@Sun.COM err = mac_maxsdu_update(hxgep->mach, new_mtu); 31827584SQiyan.Sun@Sun.COM if (err) { 31837584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize = 31847584SQiyan.Sun@Sun.COM (uint16_t)old_framesize; 31857584SQiyan.Sun@Sun.COM (void) hxge_vmac_set_framesize(hxgep); 31867584SQiyan.Sun@Sun.COM } 31877584SQiyan.Sun@Sun.COM 31887584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 31897584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: set MTU: %d maxframe %d", 31907584SQiyan.Sun@Sun.COM new_mtu, hxgep->vmac.maxframesize)); 31917584SQiyan.Sun@Sun.COM break; 31927584SQiyan.Sun@Sun.COM 31937584SQiyan.Sun@Sun.COM case MAC_PROP_PRIVATE: 31947584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 31957584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: private property")); 31967584SQiyan.Sun@Sun.COM err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize, 31977584SQiyan.Sun@Sun.COM pr_val); 31987584SQiyan.Sun@Sun.COM break; 31997584SQiyan.Sun@Sun.COM 32007584SQiyan.Sun@Sun.COM default: 32017584SQiyan.Sun@Sun.COM err = ENOTSUP; 32027584SQiyan.Sun@Sun.COM break; 32037584SQiyan.Sun@Sun.COM } 32047584SQiyan.Sun@Sun.COM 32057584SQiyan.Sun@Sun.COM mutex_exit(hxgep->genlock); 32067584SQiyan.Sun@Sun.COM 32077584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 32087584SQiyan.Sun@Sun.COM "<== hxge_m_setprop (return %d)", err)); 32097584SQiyan.Sun@Sun.COM 32107584SQiyan.Sun@Sun.COM return (err); 32117584SQiyan.Sun@Sun.COM } 32127584SQiyan.Sun@Sun.COM 32137584SQiyan.Sun@Sun.COM /* ARGSUSED */ 32147584SQiyan.Sun@Sun.COM static int 32157584SQiyan.Sun@Sun.COM hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 32167584SQiyan.Sun@Sun.COM void *pr_val) 32177584SQiyan.Sun@Sun.COM { 32187584SQiyan.Sun@Sun.COM int err = 0; 32197584SQiyan.Sun@Sun.COM link_flowctrl_t fl; 32207584SQiyan.Sun@Sun.COM 32217584SQiyan.Sun@Sun.COM switch (pr_num) { 32227584SQiyan.Sun@Sun.COM case MAC_PROP_DUPLEX: 32237584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = 2; 32247584SQiyan.Sun@Sun.COM break; 32257584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG: 32267584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = 0; 32277584SQiyan.Sun@Sun.COM break; 32287584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL: 32297584SQiyan.Sun@Sun.COM if (pr_valsize < sizeof (link_flowctrl_t)) 32307584SQiyan.Sun@Sun.COM return (EINVAL); 32317584SQiyan.Sun@Sun.COM fl = LINK_FLOWCTRL_TX; 32327584SQiyan.Sun@Sun.COM bcopy(&fl, pr_val, sizeof (fl)); 32337584SQiyan.Sun@Sun.COM break; 32347584SQiyan.Sun@Sun.COM default: 32357584SQiyan.Sun@Sun.COM err = ENOTSUP; 32367584SQiyan.Sun@Sun.COM break; 32377584SQiyan.Sun@Sun.COM } 32387584SQiyan.Sun@Sun.COM return (err); 32397584SQiyan.Sun@Sun.COM } 32407584SQiyan.Sun@Sun.COM 32417584SQiyan.Sun@Sun.COM static int 32427584SQiyan.Sun@Sun.COM hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 32437584SQiyan.Sun@Sun.COM uint_t pr_flags, uint_t pr_valsize, void *pr_val) 32447584SQiyan.Sun@Sun.COM { 32457584SQiyan.Sun@Sun.COM hxge_t *hxgep = barg; 32467584SQiyan.Sun@Sun.COM p_hxge_stats_t statsp = hxgep->statsp; 32477584SQiyan.Sun@Sun.COM int err = 0; 32487584SQiyan.Sun@Sun.COM link_flowctrl_t fl; 32497584SQiyan.Sun@Sun.COM uint64_t tmp = 0; 32507584SQiyan.Sun@Sun.COM link_state_t ls; 32517584SQiyan.Sun@Sun.COM 32527584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 32537584SQiyan.Sun@Sun.COM "==> hxge_m_getprop: pr_num %d", pr_num)); 32547584SQiyan.Sun@Sun.COM 32557584SQiyan.Sun@Sun.COM if (pr_valsize == 0) 32567584SQiyan.Sun@Sun.COM return (EINVAL); 32577584SQiyan.Sun@Sun.COM 32587584SQiyan.Sun@Sun.COM if ((pr_flags & MAC_PROP_DEFAULT) && (pr_num != MAC_PROP_PRIVATE)) { 32597584SQiyan.Sun@Sun.COM err = hxge_get_def_val(hxgep, pr_num, pr_valsize, pr_val); 32607584SQiyan.Sun@Sun.COM return (err); 32617584SQiyan.Sun@Sun.COM } 32627584SQiyan.Sun@Sun.COM 32637584SQiyan.Sun@Sun.COM bzero(pr_val, pr_valsize); 32647584SQiyan.Sun@Sun.COM switch (pr_num) { 32657584SQiyan.Sun@Sun.COM case MAC_PROP_DUPLEX: 32667584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 32677584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 32687584SQiyan.Sun@Sun.COM "==> hxge_m_getprop: duplex mode %d", 32697584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val)); 32707584SQiyan.Sun@Sun.COM break; 32717584SQiyan.Sun@Sun.COM 32727584SQiyan.Sun@Sun.COM case MAC_PROP_SPEED: 32737584SQiyan.Sun@Sun.COM if (pr_valsize < sizeof (uint64_t)) 32747584SQiyan.Sun@Sun.COM return (EINVAL); 32757584SQiyan.Sun@Sun.COM tmp = statsp->mac_stats.link_speed * 1000000ull; 32767584SQiyan.Sun@Sun.COM bcopy(&tmp, pr_val, sizeof (tmp)); 32777584SQiyan.Sun@Sun.COM break; 32787584SQiyan.Sun@Sun.COM 32797584SQiyan.Sun@Sun.COM case MAC_PROP_STATUS: 32807584SQiyan.Sun@Sun.COM if (pr_valsize < sizeof (link_state_t)) 32817584SQiyan.Sun@Sun.COM return (EINVAL); 32827584SQiyan.Sun@Sun.COM if (!statsp->mac_stats.link_up) 32837584SQiyan.Sun@Sun.COM ls = LINK_STATE_DOWN; 32847584SQiyan.Sun@Sun.COM else 32857584SQiyan.Sun@Sun.COM ls = LINK_STATE_UP; 32867584SQiyan.Sun@Sun.COM bcopy(&ls, pr_val, sizeof (ls)); 32877584SQiyan.Sun@Sun.COM break; 32887584SQiyan.Sun@Sun.COM 32897584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL: 32907584SQiyan.Sun@Sun.COM /* 32917584SQiyan.Sun@Sun.COM * Flow control is supported by the shared domain and 32927584SQiyan.Sun@Sun.COM * it is currently transmit only 32937584SQiyan.Sun@Sun.COM */ 32947584SQiyan.Sun@Sun.COM if (pr_valsize < sizeof (link_flowctrl_t)) 32957584SQiyan.Sun@Sun.COM return (EINVAL); 32967584SQiyan.Sun@Sun.COM fl = LINK_FLOWCTRL_TX; 32977584SQiyan.Sun@Sun.COM bcopy(&fl, pr_val, sizeof (fl)); 32987584SQiyan.Sun@Sun.COM break; 32997584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG: 33007584SQiyan.Sun@Sun.COM /* 10G link only and it is not negotiable */ 33017584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = 0; 33027584SQiyan.Sun@Sun.COM break; 33037584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 33047584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 33057584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 33067584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 33077584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 33087584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 33097584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 33107584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP: 33117584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP: 33127584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 33137584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP: 33147584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP: 33157584SQiyan.Sun@Sun.COM err = ENOTSUP; 33167584SQiyan.Sun@Sun.COM break; 33177584SQiyan.Sun@Sun.COM 33187584SQiyan.Sun@Sun.COM case MAC_PROP_PRIVATE: 33197584SQiyan.Sun@Sun.COM err = hxge_get_priv_prop(hxgep, pr_name, pr_flags, 33207584SQiyan.Sun@Sun.COM pr_valsize, pr_val); 33217584SQiyan.Sun@Sun.COM break; 33227584SQiyan.Sun@Sun.COM default: 33237584SQiyan.Sun@Sun.COM err = EINVAL; 33247584SQiyan.Sun@Sun.COM break; 33257584SQiyan.Sun@Sun.COM } 33267584SQiyan.Sun@Sun.COM 33277584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop")); 33287584SQiyan.Sun@Sun.COM 33297584SQiyan.Sun@Sun.COM return (err); 33307584SQiyan.Sun@Sun.COM } 33317584SQiyan.Sun@Sun.COM 33327584SQiyan.Sun@Sun.COM /* ARGSUSED */ 33337584SQiyan.Sun@Sun.COM static int 33347584SQiyan.Sun@Sun.COM hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize, 33357584SQiyan.Sun@Sun.COM const void *pr_val) 33367584SQiyan.Sun@Sun.COM { 33377584SQiyan.Sun@Sun.COM p_hxge_param_t param_arr = hxgep->param_arr; 33387584SQiyan.Sun@Sun.COM int err = 0; 33397584SQiyan.Sun@Sun.COM 33407584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 33417584SQiyan.Sun@Sun.COM "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val)); 33427584SQiyan.Sun@Sun.COM 33437584SQiyan.Sun@Sun.COM if (pr_val == NULL) { 33447584SQiyan.Sun@Sun.COM return (EINVAL); 33457584SQiyan.Sun@Sun.COM } 33467584SQiyan.Sun@Sun.COM 33477584SQiyan.Sun@Sun.COM /* Blanking */ 33487584SQiyan.Sun@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 33497584SQiyan.Sun@Sun.COM err = hxge_param_rx_intr_time(hxgep, NULL, NULL, 33507584SQiyan.Sun@Sun.COM (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_time]); 33517584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 33527584SQiyan.Sun@Sun.COM err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL, 33537584SQiyan.Sun@Sun.COM (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 33547584SQiyan.Sun@Sun.COM 33557584SQiyan.Sun@Sun.COM /* Classification */ 33567584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 33577584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33587584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 33597584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 33607584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33617584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 33627584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 33637584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33647584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 33657584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 33667584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33677584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 33687584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 33697584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33707584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 33717584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 33727584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33737584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 33747584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 33757584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33767584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 33777584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 33787584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 33797584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 33807584SQiyan.Sun@Sun.COM } else { 33817584SQiyan.Sun@Sun.COM err = EINVAL; 33827584SQiyan.Sun@Sun.COM } 33837584SQiyan.Sun@Sun.COM 33847584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 33857584SQiyan.Sun@Sun.COM "<== hxge_set_priv_prop: err %d", err)); 33867584SQiyan.Sun@Sun.COM 33877584SQiyan.Sun@Sun.COM return (err); 33887584SQiyan.Sun@Sun.COM } 33897584SQiyan.Sun@Sun.COM 33907584SQiyan.Sun@Sun.COM static int 33917584SQiyan.Sun@Sun.COM hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_flags, 33927584SQiyan.Sun@Sun.COM uint_t pr_valsize, void *pr_val) 33937584SQiyan.Sun@Sun.COM { 33947584SQiyan.Sun@Sun.COM p_hxge_param_t param_arr = hxgep->param_arr; 33957584SQiyan.Sun@Sun.COM char valstr[MAXNAMELEN]; 33967584SQiyan.Sun@Sun.COM int err = 0; 33977584SQiyan.Sun@Sun.COM uint_t strsize; 33987584SQiyan.Sun@Sun.COM int value = 0; 33997584SQiyan.Sun@Sun.COM 34007584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 34017584SQiyan.Sun@Sun.COM "==> hxge_get_priv_prop: property %s", pr_name)); 34027584SQiyan.Sun@Sun.COM 34037584SQiyan.Sun@Sun.COM if (pr_flags & MAC_PROP_DEFAULT) { 34047584SQiyan.Sun@Sun.COM /* Receive Interrupt Blanking Parameters */ 34057584SQiyan.Sun@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 34067584SQiyan.Sun@Sun.COM value = RXDMA_RCR_TO_DEFAULT; 34077584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 34087584SQiyan.Sun@Sun.COM value = RXDMA_RCR_PTHRES_DEFAULT; 34097584SQiyan.Sun@Sun.COM 34107584SQiyan.Sun@Sun.COM /* Classification and Load Distribution Configuration */ 34117584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 || 34127584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv4_udp") == 0 || 34137584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv4_ah") == 0 || 34147584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 || 34157584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 || 34167584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv6_udp") == 0 || 34177584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv6_ah") == 0 || 34187584SQiyan.Sun@Sun.COM strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 34197584SQiyan.Sun@Sun.COM value = HXGE_CLASS_TCAM_LOOKUP; 34207584SQiyan.Sun@Sun.COM } else { 34217584SQiyan.Sun@Sun.COM err = EINVAL; 34227584SQiyan.Sun@Sun.COM } 34237584SQiyan.Sun@Sun.COM } else { 34247584SQiyan.Sun@Sun.COM /* Receive Interrupt Blanking Parameters */ 34257584SQiyan.Sun@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 34267584SQiyan.Sun@Sun.COM value = hxgep->intr_timeout; 34277584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 34287584SQiyan.Sun@Sun.COM value = hxgep->intr_threshold; 34297584SQiyan.Sun@Sun.COM 34307584SQiyan.Sun@Sun.COM /* Classification and Load Distribution Configuration */ 34317584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 34327584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34337584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 34347584SQiyan.Sun@Sun.COM 34357584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv4_tcp].value; 34367584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 34377584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34387584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 34397584SQiyan.Sun@Sun.COM 34407584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv4_udp].value; 34417584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 34427584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34437584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 34447584SQiyan.Sun@Sun.COM 34457584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv4_ah].value; 34467584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 34477584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34487584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 34497584SQiyan.Sun@Sun.COM 34507584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv4_sctp].value; 34517584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 34527584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34537584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 34547584SQiyan.Sun@Sun.COM 34557584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv6_tcp].value; 34567584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 34577584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34587584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 34597584SQiyan.Sun@Sun.COM 34607584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv6_udp].value; 34617584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 34627584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34637584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 34647584SQiyan.Sun@Sun.COM 34657584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv6_ah].value; 34667584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 34677584SQiyan.Sun@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 34687584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 34697584SQiyan.Sun@Sun.COM 34707584SQiyan.Sun@Sun.COM value = (int)param_arr[param_class_opt_ipv6_sctp].value; 34717584SQiyan.Sun@Sun.COM } else { 34727584SQiyan.Sun@Sun.COM err = EINVAL; 34737584SQiyan.Sun@Sun.COM } 34747584SQiyan.Sun@Sun.COM } 34757584SQiyan.Sun@Sun.COM 34767584SQiyan.Sun@Sun.COM if (err == 0) { 34777584SQiyan.Sun@Sun.COM (void) snprintf(valstr, sizeof (valstr), "0x%x", value); 34787584SQiyan.Sun@Sun.COM 34797584SQiyan.Sun@Sun.COM strsize = (uint_t)strlen(valstr); 34807584SQiyan.Sun@Sun.COM if (pr_valsize < strsize) { 34817584SQiyan.Sun@Sun.COM err = ENOBUFS; 34827584SQiyan.Sun@Sun.COM } else { 34837584SQiyan.Sun@Sun.COM (void) strlcpy(pr_val, valstr, pr_valsize); 34847584SQiyan.Sun@Sun.COM } 34857584SQiyan.Sun@Sun.COM } 34867584SQiyan.Sun@Sun.COM 34877584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 34887584SQiyan.Sun@Sun.COM "<== hxge_get_priv_prop: return %d", err)); 34897584SQiyan.Sun@Sun.COM 34907584SQiyan.Sun@Sun.COM return (err); 34917584SQiyan.Sun@Sun.COM } 34926349Sqs148142 /* 34936349Sqs148142 * Module loading and removing entry points. 34946349Sqs148142 */ 34956349Sqs148142 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach, 3496*7918SQiyan.Sun@Sun.COM nodev, NULL, D_MP, NULL, NULL); 34976349Sqs148142 34986349Sqs148142 extern struct mod_ops mod_driverops; 34996349Sqs148142 35006349Sqs148142 #define HXGE_DESC_VER "HXGE 10Gb Ethernet Driver" 35016349Sqs148142 35026349Sqs148142 /* 35036349Sqs148142 * Module linkage information for the kernel. 35046349Sqs148142 */ 35056349Sqs148142 static struct modldrv hxge_modldrv = { 35066349Sqs148142 &mod_driverops, 35076349Sqs148142 HXGE_DESC_VER, 35086349Sqs148142 &hxge_dev_ops 35096349Sqs148142 }; 35106349Sqs148142 35116349Sqs148142 static struct modlinkage modlinkage = { 35126349Sqs148142 MODREV_1, (void *) &hxge_modldrv, NULL 35136349Sqs148142 }; 35146349Sqs148142 35156349Sqs148142 int 35166349Sqs148142 _init(void) 35176349Sqs148142 { 35186349Sqs148142 int status; 35196349Sqs148142 35206349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 35216349Sqs148142 mac_init_ops(&hxge_dev_ops, "hxge"); 35226349Sqs148142 status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0); 35236349Sqs148142 if (status != 0) { 35246349Sqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 35256349Sqs148142 "failed to init device soft state")); 35266349Sqs148142 mac_fini_ops(&hxge_dev_ops); 35276349Sqs148142 goto _init_exit; 35286349Sqs148142 } 35296349Sqs148142 35306349Sqs148142 status = mod_install(&modlinkage); 35316349Sqs148142 if (status != 0) { 35326349Sqs148142 ddi_soft_state_fini(&hxge_list); 35336349Sqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed")); 35346349Sqs148142 goto _init_exit; 35356349Sqs148142 } 35366349Sqs148142 35376349Sqs148142 MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL); 35386349Sqs148142 35396349Sqs148142 _init_exit: 35406349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 35416349Sqs148142 35426349Sqs148142 return (status); 35436349Sqs148142 } 35446349Sqs148142 35456349Sqs148142 int 35466349Sqs148142 _fini(void) 35476349Sqs148142 { 35486349Sqs148142 int status; 35496349Sqs148142 35506349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 35516349Sqs148142 35526349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 35536349Sqs148142 35546349Sqs148142 if (hxge_mblks_pending) 35556349Sqs148142 return (EBUSY); 35566349Sqs148142 35576349Sqs148142 status = mod_remove(&modlinkage); 35586349Sqs148142 if (status != DDI_SUCCESS) { 35596349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, 35606349Sqs148142 "Module removal failed 0x%08x", status)); 35616349Sqs148142 goto _fini_exit; 35626349Sqs148142 } 35636349Sqs148142 35646349Sqs148142 mac_fini_ops(&hxge_dev_ops); 35656349Sqs148142 35666349Sqs148142 ddi_soft_state_fini(&hxge_list); 35676349Sqs148142 35686349Sqs148142 MUTEX_DESTROY(&hxge_common_lock); 35696349Sqs148142 35706349Sqs148142 _fini_exit: 35716349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 35726349Sqs148142 35736349Sqs148142 return (status); 35746349Sqs148142 } 35756349Sqs148142 35766349Sqs148142 int 35776349Sqs148142 _info(struct modinfo *modinfop) 35786349Sqs148142 { 35796349Sqs148142 int status; 35806349Sqs148142 35816349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 35826349Sqs148142 status = mod_info(&modlinkage, modinfop); 35836349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 35846349Sqs148142 35856349Sqs148142 return (status); 35866349Sqs148142 } 35876349Sqs148142 35886349Sqs148142 /*ARGSUSED*/ 35896349Sqs148142 hxge_status_t 35906349Sqs148142 hxge_add_intrs(p_hxge_t hxgep) 35916349Sqs148142 { 35926349Sqs148142 int intr_types; 35936349Sqs148142 int type = 0; 35946349Sqs148142 int ddi_status = DDI_SUCCESS; 35956349Sqs148142 hxge_status_t status = HXGE_OK; 35966349Sqs148142 35976349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs")); 35986349Sqs148142 35996349Sqs148142 hxgep->hxge_intr_type.intr_registered = B_FALSE; 36006349Sqs148142 hxgep->hxge_intr_type.intr_enabled = B_FALSE; 36016349Sqs148142 hxgep->hxge_intr_type.msi_intx_cnt = 0; 36026349Sqs148142 hxgep->hxge_intr_type.intr_added = 0; 36036349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable = B_FALSE; 36046349Sqs148142 hxgep->hxge_intr_type.intr_type = 0; 36056349Sqs148142 36066349Sqs148142 if (hxge_msi_enable) { 36076349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable = B_TRUE; 36086349Sqs148142 } 36096349Sqs148142 36106349Sqs148142 /* Get the supported interrupt types */ 36116349Sqs148142 if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types)) 36126349Sqs148142 != DDI_SUCCESS) { 36136349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: " 36146349Sqs148142 "ddi_intr_get_supported_types failed: status 0x%08x", 36156349Sqs148142 ddi_status)); 36166349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 36176349Sqs148142 } 36186349Sqs148142 36196349Sqs148142 hxgep->hxge_intr_type.intr_types = intr_types; 36206349Sqs148142 36216349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 36226349Sqs148142 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 36236349Sqs148142 36246349Sqs148142 /* 36256349Sqs148142 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable: 36266349Sqs148142 * (1): 1 - MSI 36276349Sqs148142 * (2): 2 - MSI-X 36286349Sqs148142 * others - FIXED 36296349Sqs148142 */ 36306349Sqs148142 switch (hxge_msi_enable) { 36316349Sqs148142 default: 36326349Sqs148142 type = DDI_INTR_TYPE_FIXED; 36336349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 36346349Sqs148142 "use fixed (intx emulation) type %08x", type)); 36356349Sqs148142 break; 36366349Sqs148142 36376349Sqs148142 case 2: 36386349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 36396349Sqs148142 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 36406349Sqs148142 if (intr_types & DDI_INTR_TYPE_MSIX) { 36416349Sqs148142 type = DDI_INTR_TYPE_MSIX; 36426349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 36436349Sqs148142 "==> hxge_add_intrs: " 36446349Sqs148142 "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 36456349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_MSI) { 36466349Sqs148142 type = DDI_INTR_TYPE_MSI; 36476349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 36486349Sqs148142 "==> hxge_add_intrs: " 36496349Sqs148142 "ddi_intr_get_supported_types: MSI 0x%08x", type)); 36506349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 36516349Sqs148142 type = DDI_INTR_TYPE_FIXED; 36526349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 36536349Sqs148142 "ddi_intr_get_supported_types: MSXED0x%08x", type)); 36546349Sqs148142 } 36556349Sqs148142 break; 36566349Sqs148142 36576349Sqs148142 case 1: 36586349Sqs148142 if (intr_types & DDI_INTR_TYPE_MSI) { 36596349Sqs148142 type = DDI_INTR_TYPE_MSI; 36606349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 36616349Sqs148142 "==> hxge_add_intrs: " 36626349Sqs148142 "ddi_intr_get_supported_types: MSI 0x%08x", type)); 36636349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_MSIX) { 36646349Sqs148142 type = DDI_INTR_TYPE_MSIX; 36656349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 36666349Sqs148142 "==> hxge_add_intrs: " 36676349Sqs148142 "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 36686349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 36696349Sqs148142 type = DDI_INTR_TYPE_FIXED; 36706349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 36716349Sqs148142 "==> hxge_add_intrs: " 36726349Sqs148142 "ddi_intr_get_supported_types: MSXED0x%08x", type)); 36736349Sqs148142 } 36746349Sqs148142 } 36756349Sqs148142 36766349Sqs148142 hxgep->hxge_intr_type.intr_type = type; 36776349Sqs148142 if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 36786349Sqs148142 type == DDI_INTR_TYPE_FIXED) && 36796349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable) { 36806349Sqs148142 if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) { 36816349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36826349Sqs148142 " hxge_add_intrs: " 36836349Sqs148142 " hxge_add_intrs_adv failed: status 0x%08x", 36846349Sqs148142 status)); 36856349Sqs148142 return (status); 36866349Sqs148142 } else { 36876349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: " 36886349Sqs148142 "interrupts registered : type %d", type)); 36896349Sqs148142 hxgep->hxge_intr_type.intr_registered = B_TRUE; 36906349Sqs148142 36916349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 36926349Sqs148142 "\nAdded advanced hxge add_intr_adv " 36936349Sqs148142 "intr type 0x%x\n", type)); 36946349Sqs148142 36956349Sqs148142 return (status); 36966349Sqs148142 } 36976349Sqs148142 } 36986349Sqs148142 36996349Sqs148142 if (!hxgep->hxge_intr_type.intr_registered) { 37006349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37016349Sqs148142 "==> hxge_add_intrs: failed to register interrupts")); 37026349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 37036349Sqs148142 } 37046349Sqs148142 37056349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs")); 37066349Sqs148142 37076349Sqs148142 return (status); 37086349Sqs148142 } 37096349Sqs148142 37106349Sqs148142 /*ARGSUSED*/ 37116349Sqs148142 static hxge_status_t 37126349Sqs148142 hxge_add_soft_intrs(p_hxge_t hxgep) 37136349Sqs148142 { 37146349Sqs148142 int ddi_status = DDI_SUCCESS; 37156349Sqs148142 hxge_status_t status = HXGE_OK; 37166349Sqs148142 37176349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_soft_intrs")); 37186349Sqs148142 37196349Sqs148142 hxgep->resched_id = NULL; 37206349Sqs148142 hxgep->resched_running = B_FALSE; 37216349Sqs148142 ddi_status = ddi_add_softintr(hxgep->dip, DDI_SOFTINT_LOW, 37226349Sqs148142 &hxgep->resched_id, NULL, NULL, hxge_reschedule, (caddr_t)hxgep); 37236349Sqs148142 if (ddi_status != DDI_SUCCESS) { 37246349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_soft_intrs: " 37256349Sqs148142 "ddi_add_softintrs failed: status 0x%08x", ddi_status)); 37266349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 37276349Sqs148142 } 37286349Sqs148142 37296349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_ddi_add_soft_intrs")); 37306349Sqs148142 37316349Sqs148142 return (status); 37326349Sqs148142 } 37336349Sqs148142 37346349Sqs148142 /*ARGSUSED*/ 37356349Sqs148142 static hxge_status_t 37366349Sqs148142 hxge_add_intrs_adv(p_hxge_t hxgep) 37376349Sqs148142 { 37386349Sqs148142 int intr_type; 37396349Sqs148142 p_hxge_intr_t intrp; 37406349Sqs148142 hxge_status_t status; 37416349Sqs148142 37426349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv")); 37436349Sqs148142 37446349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 37456349Sqs148142 intr_type = intrp->intr_type; 37466349Sqs148142 37476349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x", 37486349Sqs148142 intr_type)); 37496349Sqs148142 37506349Sqs148142 switch (intr_type) { 37516349Sqs148142 case DDI_INTR_TYPE_MSI: /* 0x2 */ 37526349Sqs148142 case DDI_INTR_TYPE_MSIX: /* 0x4 */ 37536349Sqs148142 status = hxge_add_intrs_adv_type(hxgep, intr_type); 37546349Sqs148142 break; 37556349Sqs148142 37566349Sqs148142 case DDI_INTR_TYPE_FIXED: /* 0x1 */ 37576349Sqs148142 status = hxge_add_intrs_adv_type_fix(hxgep, intr_type); 37586349Sqs148142 break; 37596349Sqs148142 37606349Sqs148142 default: 37616349Sqs148142 status = HXGE_ERROR; 37626349Sqs148142 break; 37636349Sqs148142 } 37646349Sqs148142 37656349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv")); 37666349Sqs148142 37676349Sqs148142 return (status); 37686349Sqs148142 } 37696349Sqs148142 37706349Sqs148142 /*ARGSUSED*/ 37716349Sqs148142 static hxge_status_t 37726349Sqs148142 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type) 37736349Sqs148142 { 37746349Sqs148142 dev_info_t *dip = hxgep->dip; 37756349Sqs148142 p_hxge_ldg_t ldgp; 37766349Sqs148142 p_hxge_intr_t intrp; 37776349Sqs148142 uint_t *inthandler; 37786349Sqs148142 void *arg1, *arg2; 37796349Sqs148142 int behavior; 37806349Sqs148142 int nintrs, navail; 37816349Sqs148142 int nactual, nrequired; 37826349Sqs148142 int inum = 0; 37836349Sqs148142 int loop = 0; 37846349Sqs148142 int x, y; 37856349Sqs148142 int ddi_status = DDI_SUCCESS; 37866349Sqs148142 hxge_status_t status = HXGE_OK; 37876349Sqs148142 37886349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type")); 37896349Sqs148142 37906349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 37916349Sqs148142 37926349Sqs148142 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 37936349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 37946349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37956349Sqs148142 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 37966349Sqs148142 "nintrs: %d", ddi_status, nintrs)); 37976349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 37986349Sqs148142 } 37996349Sqs148142 38006349Sqs148142 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 38016349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 38026349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38036349Sqs148142 "ddi_intr_get_navail() failed, status: 0x%x%, " 38046349Sqs148142 "nintrs: %d", ddi_status, navail)); 38056349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 38066349Sqs148142 } 38076349Sqs148142 38086349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38096349Sqs148142 "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d", 38106349Sqs148142 int_type, nintrs, navail)); 38116349Sqs148142 38126349Sqs148142 if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 38136349Sqs148142 /* MSI must be power of 2 */ 38146349Sqs148142 if ((navail & 16) == 16) { 38156349Sqs148142 navail = 16; 38166349Sqs148142 } else if ((navail & 8) == 8) { 38176349Sqs148142 navail = 8; 38186349Sqs148142 } else if ((navail & 4) == 4) { 38196349Sqs148142 navail = 4; 38206349Sqs148142 } else if ((navail & 2) == 2) { 38216349Sqs148142 navail = 2; 38226349Sqs148142 } else { 38236349Sqs148142 navail = 1; 38246349Sqs148142 } 38256349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38266349Sqs148142 "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 38276349Sqs148142 "navail %d", nintrs, navail)); 38286349Sqs148142 } 38296349Sqs148142 38306349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38316349Sqs148142 "requesting: intr type %d nintrs %d, navail %d", 38326349Sqs148142 int_type, nintrs, navail)); 38336349Sqs148142 38346349Sqs148142 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 38356349Sqs148142 DDI_INTR_ALLOC_NORMAL); 38366349Sqs148142 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 38376349Sqs148142 intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP); 38386349Sqs148142 38396349Sqs148142 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 38406349Sqs148142 navail, &nactual, behavior); 38416349Sqs148142 if (ddi_status != DDI_SUCCESS || nactual == 0) { 38426349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38436349Sqs148142 " ddi_intr_alloc() failed: %d", ddi_status)); 38446349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 38456349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 38466349Sqs148142 } 38476349Sqs148142 38486349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38496349Sqs148142 "ddi_intr_alloc() returned: navail %d nactual %d", 38506349Sqs148142 navail, nactual)); 38516349Sqs148142 38526349Sqs148142 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 38536349Sqs148142 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 38546349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38556349Sqs148142 " ddi_intr_get_pri() failed: %d", ddi_status)); 38566349Sqs148142 /* Free already allocated interrupts */ 38576349Sqs148142 for (y = 0; y < nactual; y++) { 38586349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 38596349Sqs148142 } 38606349Sqs148142 38616349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 38626349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 38636349Sqs148142 } 38646349Sqs148142 38656349Sqs148142 nrequired = 0; 38666349Sqs148142 status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 38676349Sqs148142 if (status != HXGE_OK) { 38686349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38696349Sqs148142 "hxge_add_intrs_adv_typ:hxge_ldgv_init " 38706349Sqs148142 "failed: 0x%x", status)); 38716349Sqs148142 /* Free already allocated interrupts */ 38726349Sqs148142 for (y = 0; y < nactual; y++) { 38736349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 38746349Sqs148142 } 38756349Sqs148142 38766349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 38776349Sqs148142 return (status); 38786349Sqs148142 } 38796349Sqs148142 38806349Sqs148142 ldgp = hxgep->ldgvp->ldgp; 38816349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38826349Sqs148142 "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual)); 38836349Sqs148142 38846349Sqs148142 if (nactual < nrequired) 38856349Sqs148142 loop = nactual; 38866349Sqs148142 else 38876349Sqs148142 loop = nrequired; 38886349Sqs148142 38896349Sqs148142 for (x = 0; x < loop; x++, ldgp++) { 38906349Sqs148142 ldgp->vector = (uint8_t)x; 38916349Sqs148142 arg1 = ldgp->ldvp; 38926349Sqs148142 arg2 = hxgep; 38936349Sqs148142 if (ldgp->nldvs == 1) { 38946349Sqs148142 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 38956349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 38966349Sqs148142 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 38976349Sqs148142 "1-1 int handler (entry %d)\n", 38986349Sqs148142 arg1, arg2, x)); 38996349Sqs148142 } else if (ldgp->nldvs > 1) { 39006349Sqs148142 inthandler = (uint_t *)ldgp->sys_intr_handler; 39016349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 39026349Sqs148142 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 39036349Sqs148142 "nldevs %d int handler (entry %d)\n", 39046349Sqs148142 arg1, arg2, ldgp->nldvs, x)); 39056349Sqs148142 } 39066349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 39076349Sqs148142 "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 39086349Sqs148142 "htable 0x%llx", x, intrp->htable[x])); 39096349Sqs148142 39106349Sqs148142 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 39116349Sqs148142 (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 39126349Sqs148142 DDI_SUCCESS) { 39136349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 39146349Sqs148142 "==> hxge_add_intrs_adv_type: failed #%d " 39156349Sqs148142 "status 0x%x", x, ddi_status)); 39166349Sqs148142 for (y = 0; y < intrp->intr_added; y++) { 39176349Sqs148142 (void) ddi_intr_remove_handler( 39186349Sqs148142 intrp->htable[y]); 39196349Sqs148142 } 39206349Sqs148142 39216349Sqs148142 /* Free already allocated intr */ 39226349Sqs148142 for (y = 0; y < nactual; y++) { 39236349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 39246349Sqs148142 } 39256349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 39266349Sqs148142 39276349Sqs148142 (void) hxge_ldgv_uninit(hxgep); 39286349Sqs148142 39296349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 39306349Sqs148142 } 39316349Sqs148142 39326349Sqs148142 intrp->intr_added++; 39336349Sqs148142 } 39346349Sqs148142 intrp->msi_intx_cnt = nactual; 39356349Sqs148142 39366349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 39376349Sqs148142 "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 39386349Sqs148142 navail, nactual, intrp->msi_intx_cnt, intrp->intr_added)); 39396349Sqs148142 39406349Sqs148142 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 39416349Sqs148142 (void) hxge_intr_ldgv_init(hxgep); 39426349Sqs148142 39436349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type")); 39446349Sqs148142 39456349Sqs148142 return (status); 39466349Sqs148142 } 39476349Sqs148142 39486349Sqs148142 /*ARGSUSED*/ 39496349Sqs148142 static hxge_status_t 39506349Sqs148142 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type) 39516349Sqs148142 { 39526349Sqs148142 dev_info_t *dip = hxgep->dip; 39536349Sqs148142 p_hxge_ldg_t ldgp; 39546349Sqs148142 p_hxge_intr_t intrp; 39556349Sqs148142 uint_t *inthandler; 39566349Sqs148142 void *arg1, *arg2; 39576349Sqs148142 int behavior; 39586349Sqs148142 int nintrs, navail; 39596349Sqs148142 int nactual, nrequired; 39606349Sqs148142 int inum = 0; 39616349Sqs148142 int x, y; 39626349Sqs148142 int ddi_status = DDI_SUCCESS; 39636349Sqs148142 hxge_status_t status = HXGE_OK; 39646349Sqs148142 39656349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix")); 39666349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 39676349Sqs148142 39686349Sqs148142 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 39696349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 39706349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 39716349Sqs148142 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 39726349Sqs148142 "nintrs: %d", status, nintrs)); 39736349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 39746349Sqs148142 } 39756349Sqs148142 39766349Sqs148142 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 39776349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 39786349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 39796349Sqs148142 "ddi_intr_get_navail() failed, status: 0x%x%, " 39806349Sqs148142 "nintrs: %d", ddi_status, navail)); 39816349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 39826349Sqs148142 } 39836349Sqs148142 39846349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 39856349Sqs148142 "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 39866349Sqs148142 nintrs, navail)); 39876349Sqs148142 39886349Sqs148142 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 39896349Sqs148142 DDI_INTR_ALLOC_NORMAL); 39906349Sqs148142 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 39916349Sqs148142 intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 39926349Sqs148142 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 39936349Sqs148142 navail, &nactual, behavior); 39946349Sqs148142 if (ddi_status != DDI_SUCCESS || nactual == 0) { 39956349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 39966349Sqs148142 " ddi_intr_alloc() failed: %d", ddi_status)); 39976349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 39986349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 39996349Sqs148142 } 40006349Sqs148142 40016349Sqs148142 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 40026349Sqs148142 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 40036349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 40046349Sqs148142 " ddi_intr_get_pri() failed: %d", ddi_status)); 40056349Sqs148142 /* Free already allocated interrupts */ 40066349Sqs148142 for (y = 0; y < nactual; y++) { 40076349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 40086349Sqs148142 } 40096349Sqs148142 40106349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 40116349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 40126349Sqs148142 } 40136349Sqs148142 40146349Sqs148142 nrequired = 0; 40156349Sqs148142 status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 40166349Sqs148142 if (status != HXGE_OK) { 40176349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 40186349Sqs148142 "hxge_add_intrs_adv_type_fix:hxge_ldgv_init " 40196349Sqs148142 "failed: 0x%x", status)); 40206349Sqs148142 /* Free already allocated interrupts */ 40216349Sqs148142 for (y = 0; y < nactual; y++) { 40226349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 40236349Sqs148142 } 40246349Sqs148142 40256349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 40266349Sqs148142 return (status); 40276349Sqs148142 } 40286349Sqs148142 40296349Sqs148142 ldgp = hxgep->ldgvp->ldgp; 40306349Sqs148142 for (x = 0; x < nrequired; x++, ldgp++) { 40316349Sqs148142 ldgp->vector = (uint8_t)x; 40326349Sqs148142 arg1 = ldgp->ldvp; 40336349Sqs148142 arg2 = hxgep; 40346349Sqs148142 if (ldgp->nldvs == 1) { 40356349Sqs148142 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 40366349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 40376349Sqs148142 "hxge_add_intrs_adv_type_fix: " 40386349Sqs148142 "1-1 int handler(%d) ldg %d ldv %d " 40396349Sqs148142 "arg1 $%p arg2 $%p\n", 40406349Sqs148142 x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2)); 40416349Sqs148142 } else if (ldgp->nldvs > 1) { 40426349Sqs148142 inthandler = (uint_t *)ldgp->sys_intr_handler; 40436349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 40446349Sqs148142 "hxge_add_intrs_adv_type_fix: " 40456349Sqs148142 "shared ldv %d int handler(%d) ldv %d ldg %d" 40466349Sqs148142 "arg1 0x%016llx arg2 0x%016llx\n", 40476349Sqs148142 x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 40486349Sqs148142 arg1, arg2)); 40496349Sqs148142 } 40506349Sqs148142 40516349Sqs148142 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 40526349Sqs148142 (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 40536349Sqs148142 DDI_SUCCESS) { 40546349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 40556349Sqs148142 "==> hxge_add_intrs_adv_type_fix: failed #%d " 40566349Sqs148142 "status 0x%x", x, ddi_status)); 40576349Sqs148142 for (y = 0; y < intrp->intr_added; y++) { 40586349Sqs148142 (void) ddi_intr_remove_handler( 40596349Sqs148142 intrp->htable[y]); 40606349Sqs148142 } 40616349Sqs148142 for (y = 0; y < nactual; y++) { 40626349Sqs148142 (void) ddi_intr_free(intrp->htable[y]); 40636349Sqs148142 } 40646349Sqs148142 /* Free already allocated intr */ 40656349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 40666349Sqs148142 40676349Sqs148142 (void) hxge_ldgv_uninit(hxgep); 40686349Sqs148142 40696349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED); 40706349Sqs148142 } 40716349Sqs148142 intrp->intr_added++; 40726349Sqs148142 } 40736349Sqs148142 40746349Sqs148142 intrp->msi_intx_cnt = nactual; 40756349Sqs148142 40766349Sqs148142 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 40776349Sqs148142 40786349Sqs148142 status = hxge_intr_ldgv_init(hxgep); 40796349Sqs148142 40806349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix")); 40816349Sqs148142 40826349Sqs148142 return (status); 40836349Sqs148142 } 40846349Sqs148142 40856349Sqs148142 /*ARGSUSED*/ 40866349Sqs148142 static void 40876349Sqs148142 hxge_remove_intrs(p_hxge_t hxgep) 40886349Sqs148142 { 40896349Sqs148142 int i, inum; 40906349Sqs148142 p_hxge_intr_t intrp; 40916349Sqs148142 40926349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs")); 40936349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 40946349Sqs148142 if (!intrp->intr_registered) { 40956349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 40966349Sqs148142 "<== hxge_remove_intrs: interrupts not registered")); 40976349Sqs148142 return; 40986349Sqs148142 } 40996349Sqs148142 41006349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced")); 41016349Sqs148142 41026349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 41036349Sqs148142 (void) ddi_intr_block_disable(intrp->htable, 41046349Sqs148142 intrp->intr_added); 41056349Sqs148142 } else { 41066349Sqs148142 for (i = 0; i < intrp->intr_added; i++) { 41076349Sqs148142 (void) ddi_intr_disable(intrp->htable[i]); 41086349Sqs148142 } 41096349Sqs148142 } 41106349Sqs148142 41116349Sqs148142 for (inum = 0; inum < intrp->intr_added; inum++) { 41126349Sqs148142 if (intrp->htable[inum]) { 41136349Sqs148142 (void) ddi_intr_remove_handler(intrp->htable[inum]); 41146349Sqs148142 } 41156349Sqs148142 } 41166349Sqs148142 41176349Sqs148142 for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 41186349Sqs148142 if (intrp->htable[inum]) { 41196349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 41206349Sqs148142 "hxge_remove_intrs: ddi_intr_free inum %d " 41216349Sqs148142 "msi_intx_cnt %d intr_added %d", 41226349Sqs148142 inum, intrp->msi_intx_cnt, intrp->intr_added)); 41236349Sqs148142 41246349Sqs148142 (void) ddi_intr_free(intrp->htable[inum]); 41256349Sqs148142 } 41266349Sqs148142 } 41276349Sqs148142 41286349Sqs148142 kmem_free(intrp->htable, intrp->intr_size); 41296349Sqs148142 intrp->intr_registered = B_FALSE; 41306349Sqs148142 intrp->intr_enabled = B_FALSE; 41316349Sqs148142 intrp->msi_intx_cnt = 0; 41326349Sqs148142 intrp->intr_added = 0; 41336349Sqs148142 41346349Sqs148142 (void) hxge_ldgv_uninit(hxgep); 41356349Sqs148142 41366349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs")); 41376349Sqs148142 } 41386349Sqs148142 41396349Sqs148142 /*ARGSUSED*/ 41406349Sqs148142 static void 41416349Sqs148142 hxge_remove_soft_intrs(p_hxge_t hxgep) 41426349Sqs148142 { 41436349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_soft_intrs")); 41446349Sqs148142 41456349Sqs148142 if (hxgep->resched_id) { 41466349Sqs148142 ddi_remove_softintr(hxgep->resched_id); 41476349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 41486349Sqs148142 "==> hxge_remove_soft_intrs: removed")); 41496349Sqs148142 hxgep->resched_id = NULL; 41506349Sqs148142 } 41516349Sqs148142 41526349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_soft_intrs")); 41536349Sqs148142 } 41546349Sqs148142 41556349Sqs148142 /*ARGSUSED*/ 41566349Sqs148142 void 41576349Sqs148142 hxge_intrs_enable(p_hxge_t hxgep) 41586349Sqs148142 { 41596349Sqs148142 p_hxge_intr_t intrp; 41606349Sqs148142 int i; 41616349Sqs148142 int status; 41626349Sqs148142 41636349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable")); 41646349Sqs148142 41656349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 41666349Sqs148142 41676349Sqs148142 if (!intrp->intr_registered) { 41686349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: " 41696349Sqs148142 "interrupts are not registered")); 41706349Sqs148142 return; 41716349Sqs148142 } 41726349Sqs148142 41736349Sqs148142 if (intrp->intr_enabled) { 41746349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 41756349Sqs148142 "<== hxge_intrs_enable: already enabled")); 41766349Sqs148142 return; 41776349Sqs148142 } 41786349Sqs148142 41796349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 41806349Sqs148142 status = ddi_intr_block_enable(intrp->htable, 41816349Sqs148142 intrp->intr_added); 41826349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 41836349Sqs148142 "block enable - status 0x%x total inums #%d\n", 41846349Sqs148142 status, intrp->intr_added)); 41856349Sqs148142 } else { 41866349Sqs148142 for (i = 0; i < intrp->intr_added; i++) { 41876349Sqs148142 status = ddi_intr_enable(intrp->htable[i]); 41886349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 41896349Sqs148142 "ddi_intr_enable:enable - status 0x%x " 41906349Sqs148142 "total inums %d enable inum #%d\n", 41916349Sqs148142 status, intrp->intr_added, i)); 41926349Sqs148142 if (status == DDI_SUCCESS) { 41936349Sqs148142 intrp->intr_enabled = B_TRUE; 41946349Sqs148142 } 41956349Sqs148142 } 41966349Sqs148142 } 41976349Sqs148142 41986349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable")); 41996349Sqs148142 } 42006349Sqs148142 42016349Sqs148142 /*ARGSUSED*/ 42026349Sqs148142 static void 42036349Sqs148142 hxge_intrs_disable(p_hxge_t hxgep) 42046349Sqs148142 { 42056349Sqs148142 p_hxge_intr_t intrp; 42066349Sqs148142 int i; 42076349Sqs148142 42086349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable")); 42096349Sqs148142 42106349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 42116349Sqs148142 42126349Sqs148142 if (!intrp->intr_registered) { 42136349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: " 42146349Sqs148142 "interrupts are not registered")); 42156349Sqs148142 return; 42166349Sqs148142 } 42176349Sqs148142 42186349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 42196349Sqs148142 (void) ddi_intr_block_disable(intrp->htable, 42206349Sqs148142 intrp->intr_added); 42216349Sqs148142 } else { 42226349Sqs148142 for (i = 0; i < intrp->intr_added; i++) { 42236349Sqs148142 (void) ddi_intr_disable(intrp->htable[i]); 42246349Sqs148142 } 42256349Sqs148142 } 42266349Sqs148142 42276349Sqs148142 intrp->intr_enabled = B_FALSE; 42286349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable")); 42296349Sqs148142 } 42306349Sqs148142 42316349Sqs148142 static hxge_status_t 42326349Sqs148142 hxge_mac_register(p_hxge_t hxgep) 42336349Sqs148142 { 42346349Sqs148142 mac_register_t *macp; 42356349Sqs148142 int status; 42366349Sqs148142 42376349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register")); 42386349Sqs148142 42396349Sqs148142 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 42406349Sqs148142 return (HXGE_ERROR); 42416349Sqs148142 42426349Sqs148142 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 42436349Sqs148142 macp->m_driver = hxgep; 42446349Sqs148142 macp->m_dip = hxgep->dip; 42456349Sqs148142 macp->m_src_addr = hxgep->ouraddr.ether_addr_octet; 42466349Sqs148142 42476349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 42486349Sqs148142 "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x", 42496349Sqs148142 macp->m_src_addr[0], 42506349Sqs148142 macp->m_src_addr[1], 42516349Sqs148142 macp->m_src_addr[2], 42526349Sqs148142 macp->m_src_addr[3], 42536349Sqs148142 macp->m_src_addr[4], 42546349Sqs148142 macp->m_src_addr[5])); 42556349Sqs148142 42566349Sqs148142 macp->m_callbacks = &hxge_m_callbacks; 42576349Sqs148142 macp->m_min_sdu = 0; 42587584SQiyan.Sun@Sun.COM macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE; 42597584SQiyan.Sun@Sun.COM macp->m_margin = VLAN_TAGSZ; 42607584SQiyan.Sun@Sun.COM macp->m_priv_props = hxge_priv_props; 42617584SQiyan.Sun@Sun.COM macp->m_priv_prop_count = HXGE_MAX_PRIV_PROPS; 42626349Sqs148142 42636349Sqs148142 status = mac_register(macp, &hxgep->mach); 42646349Sqs148142 mac_free(macp); 42656349Sqs148142 42666349Sqs148142 if (status != 0) { 42676349Sqs148142 cmn_err(CE_WARN, 42686349Sqs148142 "hxge_mac_register failed (status %d instance %d)", 42696349Sqs148142 status, hxgep->instance); 42706349Sqs148142 return (HXGE_ERROR); 42716349Sqs148142 } 42726349Sqs148142 42736349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success " 42746349Sqs148142 "(instance %d)", hxgep->instance)); 42756349Sqs148142 42766349Sqs148142 return (HXGE_OK); 42776349Sqs148142 } 42786349Sqs148142 42796349Sqs148142 static int 42806349Sqs148142 hxge_init_common_dev(p_hxge_t hxgep) 42816349Sqs148142 { 42826349Sqs148142 p_hxge_hw_list_t hw_p; 42836349Sqs148142 dev_info_t *p_dip; 42846349Sqs148142 42856349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev")); 42866349Sqs148142 42876349Sqs148142 p_dip = hxgep->p_dip; 42886349Sqs148142 MUTEX_ENTER(&hxge_common_lock); 42896349Sqs148142 42906349Sqs148142 /* 42916349Sqs148142 * Loop through existing per Hydra hardware list. 42926349Sqs148142 */ 42936349Sqs148142 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 42946349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42956349Sqs148142 "==> hxge_init_common_dev: hw_p $%p parent dip $%p", 42966349Sqs148142 hw_p, p_dip)); 42976349Sqs148142 if (hw_p->parent_devp == p_dip) { 42986349Sqs148142 hxgep->hxge_hw_p = hw_p; 42996349Sqs148142 hw_p->ndevs++; 43006349Sqs148142 hw_p->hxge_p = hxgep; 43016349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43026349Sqs148142 "==> hxge_init_common_device: " 43036349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (found)", 43046349Sqs148142 hw_p, p_dip, hw_p->ndevs)); 43056349Sqs148142 break; 43066349Sqs148142 } 43076349Sqs148142 } 43086349Sqs148142 43096349Sqs148142 if (hw_p == NULL) { 43106349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43116349Sqs148142 "==> hxge_init_common_dev: parent dip $%p (new)", p_dip)); 43126349Sqs148142 hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP); 43136349Sqs148142 hw_p->parent_devp = p_dip; 43146349Sqs148142 hw_p->magic = HXGE_MAGIC; 43156349Sqs148142 hxgep->hxge_hw_p = hw_p; 43166349Sqs148142 hw_p->ndevs++; 43176349Sqs148142 hw_p->hxge_p = hxgep; 43186349Sqs148142 hw_p->next = hxge_hw_list; 43196349Sqs148142 43206349Sqs148142 MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 43216349Sqs148142 MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 43226349Sqs148142 MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 43236349Sqs148142 43246349Sqs148142 hxge_hw_list = hw_p; 43256349Sqs148142 } 43266349Sqs148142 MUTEX_EXIT(&hxge_common_lock); 43276349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43286349Sqs148142 "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 43296349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev")); 43306349Sqs148142 43316349Sqs148142 return (HXGE_OK); 43326349Sqs148142 } 43336349Sqs148142 43346349Sqs148142 static void 43356349Sqs148142 hxge_uninit_common_dev(p_hxge_t hxgep) 43366349Sqs148142 { 43376349Sqs148142 p_hxge_hw_list_t hw_p, h_hw_p; 43386349Sqs148142 dev_info_t *p_dip; 43396349Sqs148142 43406349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev")); 43416349Sqs148142 if (hxgep->hxge_hw_p == NULL) { 43426349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43436349Sqs148142 "<== hxge_uninit_common_dev (no common)")); 43446349Sqs148142 return; 43456349Sqs148142 } 43466349Sqs148142 43476349Sqs148142 MUTEX_ENTER(&hxge_common_lock); 43486349Sqs148142 h_hw_p = hxge_hw_list; 43496349Sqs148142 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 43506349Sqs148142 p_dip = hw_p->parent_devp; 43516349Sqs148142 if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip && 43526349Sqs148142 hxgep->hxge_hw_p->magic == HXGE_MAGIC && 43536349Sqs148142 hw_p->magic == HXGE_MAGIC) { 43546349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43556349Sqs148142 "==> hxge_uninit_common_dev: " 43566349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (found)", 43576349Sqs148142 hw_p, p_dip, hw_p->ndevs)); 43586349Sqs148142 43596349Sqs148142 hxgep->hxge_hw_p = NULL; 43606349Sqs148142 if (hw_p->ndevs) { 43616349Sqs148142 hw_p->ndevs--; 43626349Sqs148142 } 43636349Sqs148142 hw_p->hxge_p = NULL; 43646349Sqs148142 if (!hw_p->ndevs) { 43656349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_vlan_lock); 43666349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_tcam_lock); 43676349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_cfg_lock); 43686349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43696349Sqs148142 "==> hxge_uninit_common_dev: " 43706349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (last)", 43716349Sqs148142 hw_p, p_dip, hw_p->ndevs)); 43726349Sqs148142 43736349Sqs148142 if (hw_p == hxge_hw_list) { 43746349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43756349Sqs148142 "==> hxge_uninit_common_dev:" 43766349Sqs148142 "remove head " 43776349Sqs148142 "hw_p $%p parent dip $%p " 43786349Sqs148142 "ndevs %d (head)", 43796349Sqs148142 hw_p, p_dip, hw_p->ndevs)); 43806349Sqs148142 hxge_hw_list = hw_p->next; 43816349Sqs148142 } else { 43826349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 43836349Sqs148142 "==> hxge_uninit_common_dev:" 43846349Sqs148142 "remove middle " 43856349Sqs148142 "hw_p $%p parent dip $%p " 43866349Sqs148142 "ndevs %d (middle)", 43876349Sqs148142 hw_p, p_dip, hw_p->ndevs)); 43886349Sqs148142 h_hw_p->next = hw_p->next; 43896349Sqs148142 } 43906349Sqs148142 43916349Sqs148142 KMEM_FREE(hw_p, sizeof (hxge_hw_list_t)); 43926349Sqs148142 } 43936349Sqs148142 break; 43946349Sqs148142 } else { 43956349Sqs148142 h_hw_p = hw_p; 43966349Sqs148142 } 43976349Sqs148142 } 43986349Sqs148142 43996349Sqs148142 MUTEX_EXIT(&hxge_common_lock); 44006349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 44016349Sqs148142 "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 44026349Sqs148142 44036349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev")); 44046349Sqs148142 } 44057584SQiyan.Sun@Sun.COM 44067584SQiyan.Sun@Sun.COM static void 44077584SQiyan.Sun@Sun.COM hxge_link_poll(void *arg) 44087584SQiyan.Sun@Sun.COM { 44097584SQiyan.Sun@Sun.COM p_hxge_t hxgep = (p_hxge_t)arg; 44107584SQiyan.Sun@Sun.COM hpi_handle_t handle; 44117584SQiyan.Sun@Sun.COM p_hxge_stats_t statsp; 44127584SQiyan.Sun@Sun.COM cip_link_stat_t link_stat; 44137584SQiyan.Sun@Sun.COM hxge_timeout *to = &hxgep->timeout; 44147584SQiyan.Sun@Sun.COM 44157584SQiyan.Sun@Sun.COM handle = HXGE_DEV_HPI_HANDLE(hxgep); 44167584SQiyan.Sun@Sun.COM statsp = (p_hxge_stats_t)hxgep->statsp; 44177584SQiyan.Sun@Sun.COM HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value); 44187584SQiyan.Sun@Sun.COM 44197584SQiyan.Sun@Sun.COM if (to->link_status != link_stat.bits.xpcs0_link_up) { 44207584SQiyan.Sun@Sun.COM to->link_status = link_stat.bits.xpcs0_link_up; 44217584SQiyan.Sun@Sun.COM 44227584SQiyan.Sun@Sun.COM if (link_stat.bits.xpcs0_link_up) { 44237584SQiyan.Sun@Sun.COM mac_link_update(hxgep->mach, LINK_STATE_UP); 44247584SQiyan.Sun@Sun.COM statsp->mac_stats.link_speed = 10000; 44257584SQiyan.Sun@Sun.COM statsp->mac_stats.link_duplex = 2; 44267584SQiyan.Sun@Sun.COM statsp->mac_stats.link_up = 1; 44277584SQiyan.Sun@Sun.COM } else { 44287584SQiyan.Sun@Sun.COM mac_link_update(hxgep->mach, LINK_STATE_DOWN); 44297584SQiyan.Sun@Sun.COM statsp->mac_stats.link_speed = 0; 44307584SQiyan.Sun@Sun.COM statsp->mac_stats.link_duplex = 0; 44317584SQiyan.Sun@Sun.COM statsp->mac_stats.link_up = 0; 44327584SQiyan.Sun@Sun.COM } 44337584SQiyan.Sun@Sun.COM } 44347584SQiyan.Sun@Sun.COM 44357584SQiyan.Sun@Sun.COM /* Restart the link status timer to check the link status */ 44367584SQiyan.Sun@Sun.COM MUTEX_ENTER(&to->lock); 44377584SQiyan.Sun@Sun.COM to->id = timeout(hxge_link_poll, arg, to->ticks); 44387584SQiyan.Sun@Sun.COM MUTEX_EXIT(&to->lock); 44397584SQiyan.Sun@Sun.COM } 4440