13dec9fcdSqs /* 23dec9fcdSqs * CDDL HEADER START 33dec9fcdSqs * 43dec9fcdSqs * The contents of this file are subject to the terms of the 53dec9fcdSqs * Common Development and Distribution License (the "License"). 63dec9fcdSqs * You may not use this file except in compliance with the License. 73dec9fcdSqs * 83dec9fcdSqs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93dec9fcdSqs * or http://www.opensolaris.org/os/licensing. 103dec9fcdSqs * See the License for the specific language governing permissions 113dec9fcdSqs * and limitations under the License. 123dec9fcdSqs * 133dec9fcdSqs * When distributing Covered Code, include this CDDL HEADER in each 143dec9fcdSqs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153dec9fcdSqs * If applicable, add the following below this CDDL HEADER, with the 163dec9fcdSqs * fields enclosed by brackets "[]" replaced with your own identifying 173dec9fcdSqs * information: Portions Copyright [yyyy] [name of copyright owner] 183dec9fcdSqs * 193dec9fcdSqs * CDDL HEADER END 203dec9fcdSqs */ 213dec9fcdSqs /* 223dec9fcdSqs * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233dec9fcdSqs * Use is subject to license terms. 243dec9fcdSqs */ 253dec9fcdSqs 263dec9fcdSqs /* 273dec9fcdSqs * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver. 283dec9fcdSqs */ 293dec9fcdSqs #include <hxge_impl.h> 303dec9fcdSqs #include <hxge_pfc.h> 313dec9fcdSqs 323dec9fcdSqs /* 333dec9fcdSqs * PSARC/2007/453 MSI-X interrupt limit override 343dec9fcdSqs * (This PSARC case is limited to MSI-X vectors 353dec9fcdSqs * and SPARC platforms only). 363dec9fcdSqs */ 373dec9fcdSqs #if defined(_BIG_ENDIAN) 383dec9fcdSqs uint32_t hxge_msi_enable = 2; 393dec9fcdSqs #else 403dec9fcdSqs uint32_t hxge_msi_enable = 1; 413dec9fcdSqs #endif 423dec9fcdSqs 433dec9fcdSqs /* 443dec9fcdSqs * Globals: tunable parameters (/etc/system or adb) 453dec9fcdSqs * 463dec9fcdSqs */ 473dec9fcdSqs uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT; 483dec9fcdSqs uint32_t hxge_rbr_spare_size = 0; 493dec9fcdSqs uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT; 503dec9fcdSqs uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT; 513dec9fcdSqs uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX; 523dec9fcdSqs uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN; 533dec9fcdSqs uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN; 54*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE; 553dec9fcdSqs 563dec9fcdSqs static hxge_os_mutex_t hxgedebuglock; 573dec9fcdSqs static int hxge_debug_init = 0; 583dec9fcdSqs 593dec9fcdSqs /* 603dec9fcdSqs * Debugging flags: 613dec9fcdSqs * hxge_no_tx_lb : transmit load balancing 623dec9fcdSqs * hxge_tx_lb_policy: 0 - TCP/UDP port (default) 633dec9fcdSqs * 1 - From the Stack 643dec9fcdSqs * 2 - Destination IP Address 653dec9fcdSqs */ 663dec9fcdSqs uint32_t hxge_no_tx_lb = 0; 673dec9fcdSqs uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP; 683dec9fcdSqs 693dec9fcdSqs /* 703dec9fcdSqs * Add tunable to reduce the amount of time spent in the 713dec9fcdSqs * ISR doing Rx Processing. 723dec9fcdSqs */ 733dec9fcdSqs uint32_t hxge_max_rx_pkts = 1024; 743dec9fcdSqs 753dec9fcdSqs /* 763dec9fcdSqs * Tunables to manage the receive buffer blocks. 773dec9fcdSqs * 783dec9fcdSqs * hxge_rx_threshold_hi: copy all buffers. 793dec9fcdSqs * hxge_rx_bcopy_size_type: receive buffer block size type. 803dec9fcdSqs * hxge_rx_threshold_lo: copy only up to tunable block size type. 813dec9fcdSqs */ 823dec9fcdSqs hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6; 833dec9fcdSqs hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 843dec9fcdSqs hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_3; 853dec9fcdSqs 863dec9fcdSqs rtrace_t hpi_rtracebuf; 873dec9fcdSqs 883dec9fcdSqs /* 893dec9fcdSqs * Function Prototypes 903dec9fcdSqs */ 913dec9fcdSqs static int hxge_attach(dev_info_t *, ddi_attach_cmd_t); 923dec9fcdSqs static int hxge_detach(dev_info_t *, ddi_detach_cmd_t); 933dec9fcdSqs static void hxge_unattach(p_hxge_t); 943dec9fcdSqs 953dec9fcdSqs static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t); 963dec9fcdSqs 973dec9fcdSqs static hxge_status_t hxge_setup_mutexes(p_hxge_t); 983dec9fcdSqs static void hxge_destroy_mutexes(p_hxge_t); 993dec9fcdSqs 1003dec9fcdSqs static hxge_status_t hxge_map_regs(p_hxge_t hxgep); 1013dec9fcdSqs static void hxge_unmap_regs(p_hxge_t hxgep); 1023dec9fcdSqs 1033dec9fcdSqs hxge_status_t hxge_add_intrs(p_hxge_t hxgep); 1043dec9fcdSqs static hxge_status_t hxge_add_soft_intrs(p_hxge_t hxgep); 1053dec9fcdSqs static void hxge_remove_intrs(p_hxge_t hxgep); 1063dec9fcdSqs static void hxge_remove_soft_intrs(p_hxge_t hxgep); 1073dec9fcdSqs static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep); 1083dec9fcdSqs static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t); 1093dec9fcdSqs static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t); 1103dec9fcdSqs void hxge_intrs_enable(p_hxge_t hxgep); 1113dec9fcdSqs static void hxge_intrs_disable(p_hxge_t hxgep); 1123dec9fcdSqs static void hxge_suspend(p_hxge_t); 1133dec9fcdSqs static hxge_status_t hxge_resume(p_hxge_t); 1143dec9fcdSqs hxge_status_t hxge_setup_dev(p_hxge_t); 1153dec9fcdSqs static void hxge_destroy_dev(p_hxge_t); 1163dec9fcdSqs hxge_status_t hxge_alloc_mem_pool(p_hxge_t); 1173dec9fcdSqs static void hxge_free_mem_pool(p_hxge_t); 1183dec9fcdSqs static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t); 1193dec9fcdSqs static void hxge_free_rx_mem_pool(p_hxge_t); 1203dec9fcdSqs static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t); 1213dec9fcdSqs static void hxge_free_tx_mem_pool(p_hxge_t); 1223dec9fcdSqs static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t, 1233dec9fcdSqs struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t, 1243dec9fcdSqs p_hxge_dma_common_t); 1253dec9fcdSqs static void hxge_dma_mem_free(p_hxge_dma_common_t); 1263dec9fcdSqs static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t, 1273dec9fcdSqs p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 1283dec9fcdSqs static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 1293dec9fcdSqs static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t, 1303dec9fcdSqs p_hxge_dma_common_t *, size_t); 1313dec9fcdSqs static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 1323dec9fcdSqs static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t, 1333dec9fcdSqs p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 1343dec9fcdSqs static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 1353dec9fcdSqs static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t, 1363dec9fcdSqs p_hxge_dma_common_t *, size_t); 1373dec9fcdSqs static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 1383dec9fcdSqs static int hxge_init_common_dev(p_hxge_t); 1393dec9fcdSqs static void hxge_uninit_common_dev(p_hxge_t); 1403dec9fcdSqs 1413dec9fcdSqs /* 1423dec9fcdSqs * The next declarations are for the GLDv3 interface. 1433dec9fcdSqs */ 1443dec9fcdSqs static int hxge_m_start(void *); 1453dec9fcdSqs static void hxge_m_stop(void *); 1463dec9fcdSqs static int hxge_m_unicst(void *, const uint8_t *); 1473dec9fcdSqs static int hxge_m_multicst(void *, boolean_t, const uint8_t *); 1483dec9fcdSqs static int hxge_m_promisc(void *, boolean_t); 1493dec9fcdSqs static void hxge_m_ioctl(void *, queue_t *, mblk_t *); 1503dec9fcdSqs static void hxge_m_resources(void *); 1513dec9fcdSqs static hxge_status_t hxge_mac_register(p_hxge_t hxgep); 1523dec9fcdSqs 1533dec9fcdSqs static int hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 1543dec9fcdSqs static int hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 1553dec9fcdSqs static int hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 1563dec9fcdSqs static int hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 1573dec9fcdSqs static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *); 158*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static boolean_t hxge_param_locked(mac_prop_id_t pr_num); 159*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 160*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_valsize, const void *pr_val); 161*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 162*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_flags, uint_t pr_valsize, void *pr_val); 163*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num, 164*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_valsize, void *pr_val); 165*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, 166*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_valsize, const void *pr_val); 167*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, 168*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_flags, uint_t pr_valsize, void *pr_val); 169*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static void hxge_link_poll(void *arg); 170*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 171*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mac_priv_prop_t hxge_priv_props[] = { 172*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 173*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 174*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 175*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 176*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 177*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 178*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 179*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 180*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 181*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW} 182*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }; 183*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 184*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States #define HXGE_MAX_PRIV_PROPS \ 185*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t)) 1863dec9fcdSqs 1873dec9fcdSqs #define HXGE_MAGIC 0x4E584745UL 1883dec9fcdSqs #define MAX_DUMP_SZ 256 1893dec9fcdSqs 190*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States #define HXGE_M_CALLBACK_FLAGS \ 191*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 1923dec9fcdSqs 1933dec9fcdSqs extern mblk_t *hxge_m_tx(void *arg, mblk_t *mp); 1943dec9fcdSqs extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep); 1953dec9fcdSqs 1963dec9fcdSqs static mac_callbacks_t hxge_m_callbacks = { 1973dec9fcdSqs HXGE_M_CALLBACK_FLAGS, 1983dec9fcdSqs hxge_m_stat, 1993dec9fcdSqs hxge_m_start, 2003dec9fcdSqs hxge_m_stop, 2013dec9fcdSqs hxge_m_promisc, 2023dec9fcdSqs hxge_m_multicst, 2033dec9fcdSqs hxge_m_unicst, 2043dec9fcdSqs hxge_m_tx, 2053dec9fcdSqs hxge_m_resources, 2063dec9fcdSqs hxge_m_ioctl, 207*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_getcapab, 208*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States NULL, 209*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States NULL, 210*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_setprop, 211*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_getprop 2123dec9fcdSqs }; 2133dec9fcdSqs 2143dec9fcdSqs /* Enable debug messages as necessary. */ 215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint64_t hxge_debug_level = 0; 2163dec9fcdSqs 2173dec9fcdSqs /* 2183dec9fcdSqs * This list contains the instance structures for the Hydra 2193dec9fcdSqs * devices present in the system. The lock exists to guarantee 2203dec9fcdSqs * mutually exclusive access to the list. 2213dec9fcdSqs */ 2223dec9fcdSqs void *hxge_list = NULL; 2233dec9fcdSqs void *hxge_hw_list = NULL; 2243dec9fcdSqs hxge_os_mutex_t hxge_common_lock; 2253dec9fcdSqs 2263dec9fcdSqs extern uint64_t hpi_debug_level; 2273dec9fcdSqs 2283dec9fcdSqs extern hxge_status_t hxge_ldgv_init(); 2293dec9fcdSqs extern hxge_status_t hxge_ldgv_uninit(); 2303dec9fcdSqs extern hxge_status_t hxge_intr_ldgv_init(); 2313dec9fcdSqs extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr, 2323dec9fcdSqs ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr); 2333dec9fcdSqs extern void hxge_fm_fini(p_hxge_t hxgep); 2343dec9fcdSqs 2353dec9fcdSqs /* 2363dec9fcdSqs * Count used to maintain the number of buffers being used 2373dec9fcdSqs * by Hydra instances and loaned up to the upper layers. 2383dec9fcdSqs */ 2393dec9fcdSqs uint32_t hxge_mblks_pending = 0; 2403dec9fcdSqs 2413dec9fcdSqs /* 2423dec9fcdSqs * Device register access attributes for PIO. 2433dec9fcdSqs */ 2443dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = { 2453dec9fcdSqs DDI_DEVICE_ATTR_V0, 2463dec9fcdSqs DDI_STRUCTURE_LE_ACC, 2473dec9fcdSqs DDI_STRICTORDER_ACC, 2483dec9fcdSqs }; 2493dec9fcdSqs 2503dec9fcdSqs /* 2513dec9fcdSqs * Device descriptor access attributes for DMA. 2523dec9fcdSqs */ 2533dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = { 2543dec9fcdSqs DDI_DEVICE_ATTR_V0, 2553dec9fcdSqs DDI_STRUCTURE_LE_ACC, 2563dec9fcdSqs DDI_STRICTORDER_ACC 2573dec9fcdSqs }; 2583dec9fcdSqs 2593dec9fcdSqs /* 2603dec9fcdSqs * Device buffer access attributes for DMA. 2613dec9fcdSqs */ 2623dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = { 2633dec9fcdSqs DDI_DEVICE_ATTR_V0, 2643dec9fcdSqs DDI_STRUCTURE_BE_ACC, 2653dec9fcdSqs DDI_STRICTORDER_ACC 2663dec9fcdSqs }; 2673dec9fcdSqs 2683dec9fcdSqs ddi_dma_attr_t hxge_desc_dma_attr = { 2693dec9fcdSqs DMA_ATTR_V0, /* version number. */ 2703dec9fcdSqs 0, /* low address */ 2713dec9fcdSqs 0xffffffffffffffff, /* high address */ 2723dec9fcdSqs 0xffffffffffffffff, /* address counter max */ 2733dec9fcdSqs 0x100000, /* alignment */ 2743dec9fcdSqs 0xfc00fc, /* dlim_burstsizes */ 2753dec9fcdSqs 0x1, /* minimum transfer size */ 2763dec9fcdSqs 0xffffffffffffffff, /* maximum transfer size */ 2773dec9fcdSqs 0xffffffffffffffff, /* maximum segment size */ 2783dec9fcdSqs 1, /* scatter/gather list length */ 2793dec9fcdSqs (unsigned int)1, /* granularity */ 2803dec9fcdSqs 0 /* attribute flags */ 2813dec9fcdSqs }; 2823dec9fcdSqs 2833dec9fcdSqs ddi_dma_attr_t hxge_tx_dma_attr = { 2843dec9fcdSqs DMA_ATTR_V0, /* version number. */ 2853dec9fcdSqs 0, /* low address */ 2863dec9fcdSqs 0xffffffffffffffff, /* high address */ 2873dec9fcdSqs 0xffffffffffffffff, /* address counter max */ 2883dec9fcdSqs #if defined(_BIG_ENDIAN) 2893dec9fcdSqs 0x2000, /* alignment */ 2903dec9fcdSqs #else 2913dec9fcdSqs 0x1000, /* alignment */ 2923dec9fcdSqs #endif 2933dec9fcdSqs 0xfc00fc, /* dlim_burstsizes */ 2943dec9fcdSqs 0x1, /* minimum transfer size */ 2953dec9fcdSqs 0xffffffffffffffff, /* maximum transfer size */ 2963dec9fcdSqs 0xffffffffffffffff, /* maximum segment size */ 2973dec9fcdSqs 5, /* scatter/gather list length */ 2983dec9fcdSqs (unsigned int)1, /* granularity */ 2993dec9fcdSqs 0 /* attribute flags */ 3003dec9fcdSqs }; 3013dec9fcdSqs 3023dec9fcdSqs ddi_dma_attr_t hxge_rx_dma_attr = { 3033dec9fcdSqs DMA_ATTR_V0, /* version number. */ 3043dec9fcdSqs 0, /* low address */ 3053dec9fcdSqs 0xffffffffffffffff, /* high address */ 3063dec9fcdSqs 0xffffffffffffffff, /* address counter max */ 3073dec9fcdSqs 0x10000, /* alignment */ 3083dec9fcdSqs 0xfc00fc, /* dlim_burstsizes */ 3093dec9fcdSqs 0x1, /* minimum transfer size */ 3103dec9fcdSqs 0xffffffffffffffff, /* maximum transfer size */ 3113dec9fcdSqs 0xffffffffffffffff, /* maximum segment size */ 3123dec9fcdSqs 1, /* scatter/gather list length */ 3133dec9fcdSqs (unsigned int)1, /* granularity */ 3143dec9fcdSqs DDI_DMA_RELAXED_ORDERING /* attribute flags */ 3153dec9fcdSqs }; 3163dec9fcdSqs 3173dec9fcdSqs ddi_dma_lim_t hxge_dma_limits = { 3183dec9fcdSqs (uint_t)0, /* dlim_addr_lo */ 3193dec9fcdSqs (uint_t)0xffffffff, /* dlim_addr_hi */ 3203dec9fcdSqs (uint_t)0xffffffff, /* dlim_cntr_max */ 3213dec9fcdSqs (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 3223dec9fcdSqs 0x1, /* dlim_minxfer */ 3233dec9fcdSqs 1024 /* dlim_speed */ 3243dec9fcdSqs }; 3253dec9fcdSqs 3263dec9fcdSqs dma_method_t hxge_force_dma = DVMA; 3273dec9fcdSqs 3283dec9fcdSqs /* 3293dec9fcdSqs * dma chunk sizes. 3303dec9fcdSqs * 3313dec9fcdSqs * Try to allocate the largest possible size 3323dec9fcdSqs * so that fewer number of dma chunks would be managed 3333dec9fcdSqs */ 3343dec9fcdSqs size_t alloc_sizes[] = { 3353dec9fcdSqs 0x1000, 0x2000, 0x4000, 0x8000, 3363dec9fcdSqs 0x10000, 0x20000, 0x40000, 0x80000, 3373dec9fcdSqs 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000 3383dec9fcdSqs }; 3393dec9fcdSqs 3403dec9fcdSqs /* 3413dec9fcdSqs * Translate "dev_t" to a pointer to the associated "dev_info_t". 3423dec9fcdSqs */ 3433dec9fcdSqs static int 3443dec9fcdSqs hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3453dec9fcdSqs { 3463dec9fcdSqs p_hxge_t hxgep = NULL; 3473dec9fcdSqs int instance; 3483dec9fcdSqs int status = DDI_SUCCESS; 3493dec9fcdSqs 3503dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach")); 3513dec9fcdSqs 3523dec9fcdSqs /* 3533dec9fcdSqs * Get the device instance since we'll need to setup or retrieve a soft 3543dec9fcdSqs * state for this instance. 3553dec9fcdSqs */ 3563dec9fcdSqs instance = ddi_get_instance(dip); 3573dec9fcdSqs 3583dec9fcdSqs switch (cmd) { 3593dec9fcdSqs case DDI_ATTACH: 3603dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH")); 3613dec9fcdSqs break; 3623dec9fcdSqs 3633dec9fcdSqs case DDI_RESUME: 3643dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME")); 3653dec9fcdSqs hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 3663dec9fcdSqs if (hxgep == NULL) { 3673dec9fcdSqs status = DDI_FAILURE; 3683dec9fcdSqs break; 3693dec9fcdSqs } 3703dec9fcdSqs if (hxgep->dip != dip) { 3713dec9fcdSqs status = DDI_FAILURE; 3723dec9fcdSqs break; 3733dec9fcdSqs } 3743dec9fcdSqs if (hxgep->suspended == DDI_PM_SUSPEND) { 3753dec9fcdSqs status = ddi_dev_is_needed(hxgep->dip, 0, 1); 3763dec9fcdSqs } else { 3773dec9fcdSqs (void) hxge_resume(hxgep); 3783dec9fcdSqs } 3793dec9fcdSqs goto hxge_attach_exit; 3803dec9fcdSqs 3813dec9fcdSqs case DDI_PM_RESUME: 3823dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME")); 3833dec9fcdSqs hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 3843dec9fcdSqs if (hxgep == NULL) { 3853dec9fcdSqs status = DDI_FAILURE; 3863dec9fcdSqs break; 3873dec9fcdSqs } 3883dec9fcdSqs if (hxgep->dip != dip) { 3893dec9fcdSqs status = DDI_FAILURE; 3903dec9fcdSqs break; 3913dec9fcdSqs } 3923dec9fcdSqs (void) hxge_resume(hxgep); 3933dec9fcdSqs goto hxge_attach_exit; 3943dec9fcdSqs 3953dec9fcdSqs default: 3963dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown")); 3973dec9fcdSqs status = DDI_FAILURE; 3983dec9fcdSqs goto hxge_attach_exit; 3993dec9fcdSqs } 4003dec9fcdSqs 4013dec9fcdSqs if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) { 4023dec9fcdSqs status = DDI_FAILURE; 4033dec9fcdSqs HXGE_ERROR_MSG((hxgep, DDI_CTL, 4043dec9fcdSqs "ddi_soft_state_zalloc failed")); 4053dec9fcdSqs goto hxge_attach_exit; 4063dec9fcdSqs } 4073dec9fcdSqs 4083dec9fcdSqs hxgep = ddi_get_soft_state(hxge_list, instance); 4093dec9fcdSqs if (hxgep == NULL) { 4103dec9fcdSqs status = HXGE_ERROR; 4113dec9fcdSqs HXGE_ERROR_MSG((hxgep, DDI_CTL, 4123dec9fcdSqs "ddi_get_soft_state failed")); 4133dec9fcdSqs goto hxge_attach_fail2; 4143dec9fcdSqs } 4153dec9fcdSqs 4163dec9fcdSqs hxgep->drv_state = 0; 4173dec9fcdSqs hxgep->dip = dip; 4183dec9fcdSqs hxgep->instance = instance; 4193dec9fcdSqs hxgep->p_dip = ddi_get_parent(dip); 4203dec9fcdSqs hxgep->hxge_debug_level = hxge_debug_level; 4213dec9fcdSqs hpi_debug_level = hxge_debug_level; 4223dec9fcdSqs 4233dec9fcdSqs hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr, 4243dec9fcdSqs &hxge_rx_dma_attr); 4253dec9fcdSqs 4263dec9fcdSqs status = hxge_map_regs(hxgep); 4273dec9fcdSqs if (status != HXGE_OK) { 4283dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed")); 4293dec9fcdSqs goto hxge_attach_fail3; 4303dec9fcdSqs } 4313dec9fcdSqs 4323dec9fcdSqs status = hxge_init_common_dev(hxgep); 4333dec9fcdSqs if (status != HXGE_OK) { 4343dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4353dec9fcdSqs "hxge_init_common_dev failed")); 4363dec9fcdSqs goto hxge_attach_fail4; 4373dec9fcdSqs } 4383dec9fcdSqs 4393dec9fcdSqs /* 4403dec9fcdSqs * Setup the Ndd parameters for this instance. 4413dec9fcdSqs */ 4423dec9fcdSqs hxge_init_param(hxgep); 4433dec9fcdSqs 4443dec9fcdSqs /* 4453dec9fcdSqs * Setup Register Tracing Buffer. 4463dec9fcdSqs */ 4473dec9fcdSqs hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf); 4483dec9fcdSqs 4493dec9fcdSqs /* init stats ptr */ 4503dec9fcdSqs hxge_init_statsp(hxgep); 4513dec9fcdSqs 452*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States status = hxge_setup_mutexes(hxgep); 453*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (status != HXGE_OK) { 454*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed")); 455*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States goto hxge_attach_fail; 456*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 457*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4583dec9fcdSqs status = hxge_get_config_properties(hxgep); 4593dec9fcdSqs if (status != HXGE_OK) { 4603dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed")); 4613dec9fcdSqs goto hxge_attach_fail; 4623dec9fcdSqs } 4633dec9fcdSqs 4643dec9fcdSqs /* 4653dec9fcdSqs * Setup the Kstats for the driver. 4663dec9fcdSqs */ 4673dec9fcdSqs hxge_setup_kstats(hxgep); 4683dec9fcdSqs hxge_setup_param(hxgep); 4693dec9fcdSqs 4703dec9fcdSqs status = hxge_setup_system_dma_pages(hxgep); 4713dec9fcdSqs if (status != HXGE_OK) { 4723dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed")); 4733dec9fcdSqs goto hxge_attach_fail; 4743dec9fcdSqs } 4753dec9fcdSqs 4763dec9fcdSqs hxge_hw_id_init(hxgep); 4773dec9fcdSqs hxge_hw_init_niu_common(hxgep); 4783dec9fcdSqs 4793dec9fcdSqs status = hxge_setup_dev(hxgep); 4803dec9fcdSqs if (status != DDI_SUCCESS) { 4813dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed")); 4823dec9fcdSqs goto hxge_attach_fail; 4833dec9fcdSqs } 4843dec9fcdSqs 4853dec9fcdSqs status = hxge_add_intrs(hxgep); 4863dec9fcdSqs if (status != DDI_SUCCESS) { 4873dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed")); 4883dec9fcdSqs goto hxge_attach_fail; 4893dec9fcdSqs } 4903dec9fcdSqs 4913dec9fcdSqs status = hxge_add_soft_intrs(hxgep); 4923dec9fcdSqs if (status != DDI_SUCCESS) { 4933dec9fcdSqs HXGE_DEBUG_MSG((hxgep, HXGE_ERR_CTL, "add_soft_intr failed")); 4943dec9fcdSqs goto hxge_attach_fail; 4953dec9fcdSqs } 4963dec9fcdSqs 4973dec9fcdSqs /* 4983dec9fcdSqs * Enable interrupts. 4993dec9fcdSqs */ 5003dec9fcdSqs hxge_intrs_enable(hxgep); 5013dec9fcdSqs 5023dec9fcdSqs if ((status = hxge_mac_register(hxgep)) != HXGE_OK) { 5033dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 5043dec9fcdSqs "unable to register to mac layer (%d)", status)); 5053dec9fcdSqs goto hxge_attach_fail; 5063dec9fcdSqs } 507*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN); 508*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.link_status = 0; 509*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.ticks = drv_usectohz(2 * 1000000); 510*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 511*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Start the link status timer to check the link status */ 512*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&hxgep->timeout.lock); 513*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 514*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.ticks); 515*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&hxgep->timeout.lock); 5163dec9fcdSqs 5173dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)", 5183dec9fcdSqs instance)); 5193dec9fcdSqs 5203dec9fcdSqs goto hxge_attach_exit; 5213dec9fcdSqs 5223dec9fcdSqs hxge_attach_fail: 5233dec9fcdSqs hxge_unattach(hxgep); 5243dec9fcdSqs goto hxge_attach_fail1; 5253dec9fcdSqs 5263dec9fcdSqs hxge_attach_fail5: 5273dec9fcdSqs /* 5283dec9fcdSqs * Tear down the ndd parameters setup. 5293dec9fcdSqs */ 5303dec9fcdSqs hxge_destroy_param(hxgep); 5313dec9fcdSqs 5323dec9fcdSqs /* 5333dec9fcdSqs * Tear down the kstat setup. 5343dec9fcdSqs */ 5353dec9fcdSqs hxge_destroy_kstats(hxgep); 5363dec9fcdSqs 5373dec9fcdSqs hxge_attach_fail4: 5383dec9fcdSqs if (hxgep->hxge_hw_p) { 5393dec9fcdSqs hxge_uninit_common_dev(hxgep); 5403dec9fcdSqs hxgep->hxge_hw_p = NULL; 5413dec9fcdSqs } 5423dec9fcdSqs hxge_attach_fail3: 5433dec9fcdSqs /* 5443dec9fcdSqs * Unmap the register setup. 5453dec9fcdSqs */ 5463dec9fcdSqs hxge_unmap_regs(hxgep); 5473dec9fcdSqs 5483dec9fcdSqs hxge_fm_fini(hxgep); 5493dec9fcdSqs 5503dec9fcdSqs hxge_attach_fail2: 5513dec9fcdSqs ddi_soft_state_free(hxge_list, hxgep->instance); 5523dec9fcdSqs 5533dec9fcdSqs hxge_attach_fail1: 5543dec9fcdSqs if (status != HXGE_OK) 5553dec9fcdSqs status = (HXGE_ERROR | HXGE_DDI_FAILED); 5563dec9fcdSqs hxgep = NULL; 5573dec9fcdSqs 5583dec9fcdSqs hxge_attach_exit: 5593dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x", 5603dec9fcdSqs status)); 5613dec9fcdSqs 5623dec9fcdSqs return (status); 5633dec9fcdSqs } 5643dec9fcdSqs 5653dec9fcdSqs static int 5663dec9fcdSqs hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 5673dec9fcdSqs { 5683dec9fcdSqs int status = DDI_SUCCESS; 5693dec9fcdSqs int instance; 5703dec9fcdSqs p_hxge_t hxgep = NULL; 5713dec9fcdSqs 5723dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach")); 5733dec9fcdSqs instance = ddi_get_instance(dip); 5743dec9fcdSqs hxgep = ddi_get_soft_state(hxge_list, instance); 5753dec9fcdSqs if (hxgep == NULL) { 5763dec9fcdSqs status = DDI_FAILURE; 5773dec9fcdSqs goto hxge_detach_exit; 5783dec9fcdSqs } 5793dec9fcdSqs 5803dec9fcdSqs switch (cmd) { 5813dec9fcdSqs case DDI_DETACH: 5823dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH")); 5833dec9fcdSqs break; 5843dec9fcdSqs 5853dec9fcdSqs case DDI_PM_SUSPEND: 5863dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 5873dec9fcdSqs hxgep->suspended = DDI_PM_SUSPEND; 5883dec9fcdSqs hxge_suspend(hxgep); 5893dec9fcdSqs break; 5903dec9fcdSqs 5913dec9fcdSqs case DDI_SUSPEND: 5923dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND")); 5933dec9fcdSqs if (hxgep->suspended != DDI_PM_SUSPEND) { 5943dec9fcdSqs hxgep->suspended = DDI_SUSPEND; 5953dec9fcdSqs hxge_suspend(hxgep); 5963dec9fcdSqs } 5973dec9fcdSqs break; 5983dec9fcdSqs 5993dec9fcdSqs default: 6003dec9fcdSqs status = DDI_FAILURE; 6013dec9fcdSqs break; 6023dec9fcdSqs } 6033dec9fcdSqs 6043dec9fcdSqs if (cmd != DDI_DETACH) 6053dec9fcdSqs goto hxge_detach_exit; 6063dec9fcdSqs 6073dec9fcdSqs /* 6083dec9fcdSqs * Stop the xcvr polling. 6093dec9fcdSqs */ 6103dec9fcdSqs hxgep->suspended = cmd; 6113dec9fcdSqs 612*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Stop the link status timer before unregistering */ 613*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&hxgep->timeout.lock); 614*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (hxgep->timeout.id) 615*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) untimeout(hxgep->timeout.id); 616*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&hxgep->timeout.lock); 617*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 6183dec9fcdSqs if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) { 6193dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6203dec9fcdSqs "<== hxge_detach status = 0x%08X", status)); 6213dec9fcdSqs return (DDI_FAILURE); 6223dec9fcdSqs } 6233dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 6243dec9fcdSqs "<== hxge_detach (mac_unregister) status = 0x%08X", status)); 6253dec9fcdSqs 6263dec9fcdSqs hxge_unattach(hxgep); 6273dec9fcdSqs hxgep = NULL; 6283dec9fcdSqs 6293dec9fcdSqs hxge_detach_exit: 6303dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X", 6313dec9fcdSqs status)); 6323dec9fcdSqs 6333dec9fcdSqs return (status); 6343dec9fcdSqs } 6353dec9fcdSqs 6363dec9fcdSqs static void 6373dec9fcdSqs hxge_unattach(p_hxge_t hxgep) 6383dec9fcdSqs { 6393dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach")); 6403dec9fcdSqs 6413dec9fcdSqs if (hxgep == NULL || hxgep->dev_regs == NULL) { 6423dec9fcdSqs return; 6433dec9fcdSqs } 6443dec9fcdSqs 6453dec9fcdSqs if (hxgep->hxge_hw_p) { 6463dec9fcdSqs hxge_uninit_common_dev(hxgep); 6473dec9fcdSqs hxgep->hxge_hw_p = NULL; 6483dec9fcdSqs } 6493dec9fcdSqs 6503dec9fcdSqs if (hxgep->hxge_timerid) { 6513dec9fcdSqs hxge_stop_timer(hxgep, hxgep->hxge_timerid); 6523dec9fcdSqs hxgep->hxge_timerid = 0; 6533dec9fcdSqs } 6543dec9fcdSqs 6553dec9fcdSqs /* Stop any further interrupts. */ 6563dec9fcdSqs hxge_remove_intrs(hxgep); 6573dec9fcdSqs 6583dec9fcdSqs /* Remove soft interrups */ 6593dec9fcdSqs hxge_remove_soft_intrs(hxgep); 6603dec9fcdSqs 6613dec9fcdSqs /* Stop the device and free resources. */ 6623dec9fcdSqs hxge_destroy_dev(hxgep); 6633dec9fcdSqs 6643dec9fcdSqs /* Tear down the ndd parameters setup. */ 6653dec9fcdSqs hxge_destroy_param(hxgep); 6663dec9fcdSqs 6673dec9fcdSqs /* Tear down the kstat setup. */ 6683dec9fcdSqs hxge_destroy_kstats(hxgep); 6693dec9fcdSqs 6703dec9fcdSqs /* 6713dec9fcdSqs * Remove the list of ndd parameters which were setup during attach. 6723dec9fcdSqs */ 6733dec9fcdSqs if (hxgep->dip) { 6743dec9fcdSqs HXGE_DEBUG_MSG((hxgep, OBP_CTL, 6753dec9fcdSqs " hxge_unattach: remove all properties")); 6763dec9fcdSqs (void) ddi_prop_remove_all(hxgep->dip); 6773dec9fcdSqs } 6783dec9fcdSqs 679fe930412Sqs /* 680fe930412Sqs * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any 681fe930412Sqs * previous state before unmapping the registers. 682fe930412Sqs */ 683fe930412Sqs HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E); 684fe930412Sqs HXGE_DELAY(1000); 685fe930412Sqs 6863dec9fcdSqs /* 6873dec9fcdSqs * Unmap the register setup. 6883dec9fcdSqs */ 6893dec9fcdSqs hxge_unmap_regs(hxgep); 6903dec9fcdSqs 6913dec9fcdSqs hxge_fm_fini(hxgep); 6923dec9fcdSqs 693*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Destroy all mutexes. */ 694*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_destroy_mutexes(hxgep); 695*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 6963dec9fcdSqs /* 6973dec9fcdSqs * Free the soft state data structures allocated with this instance. 6983dec9fcdSqs */ 6993dec9fcdSqs ddi_soft_state_free(hxge_list, hxgep->instance); 7003dec9fcdSqs 7013dec9fcdSqs HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach")); 7023dec9fcdSqs } 7033dec9fcdSqs 7043dec9fcdSqs static hxge_status_t 7053dec9fcdSqs hxge_map_regs(p_hxge_t hxgep) 7063dec9fcdSqs { 7073dec9fcdSqs int ddi_status = DDI_SUCCESS; 7083dec9fcdSqs p_dev_regs_t dev_regs; 7093dec9fcdSqs 7103dec9fcdSqs #ifdef HXGE_DEBUG 7113dec9fcdSqs char *sysname; 7123dec9fcdSqs #endif 7133dec9fcdSqs 7143dec9fcdSqs off_t regsize; 7153dec9fcdSqs hxge_status_t status = HXGE_OK; 7163dec9fcdSqs int nregs; 7173dec9fcdSqs 7183dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs")); 7193dec9fcdSqs 7203dec9fcdSqs if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS) 7213dec9fcdSqs return (HXGE_ERROR); 7223dec9fcdSqs 7233dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs)); 7243dec9fcdSqs 7253dec9fcdSqs hxgep->dev_regs = NULL; 7263dec9fcdSqs dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 7273dec9fcdSqs dev_regs->hxge_regh = NULL; 7283dec9fcdSqs dev_regs->hxge_pciregh = NULL; 7293dec9fcdSqs dev_regs->hxge_msix_regh = NULL; 7303dec9fcdSqs 7313dec9fcdSqs (void) ddi_dev_regsize(hxgep->dip, 0, ®size); 7323dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7333dec9fcdSqs "hxge_map_regs: pci config size 0x%x", regsize)); 7343dec9fcdSqs 7353dec9fcdSqs ddi_status = ddi_regs_map_setup(hxgep->dip, 0, 7363dec9fcdSqs (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0, 7373dec9fcdSqs &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh); 7383dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 7393dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7403dec9fcdSqs "ddi_map_regs, hxge bus config regs failed")); 7413dec9fcdSqs goto hxge_map_regs_fail0; 7423dec9fcdSqs } 7433dec9fcdSqs 7443dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7453dec9fcdSqs "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx", 7463dec9fcdSqs dev_regs->hxge_pciregp, 7473dec9fcdSqs dev_regs->hxge_pciregh)); 7483dec9fcdSqs 7493dec9fcdSqs (void) ddi_dev_regsize(hxgep->dip, 1, ®size); 7503dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7513dec9fcdSqs "hxge_map_regs: pio size 0x%x", regsize)); 7523dec9fcdSqs 7533dec9fcdSqs /* set up the device mapped register */ 7543dec9fcdSqs ddi_status = ddi_regs_map_setup(hxgep->dip, 1, 7553dec9fcdSqs (caddr_t *)&(dev_regs->hxge_regp), 0, 0, 7563dec9fcdSqs &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh); 7573dec9fcdSqs 7583dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 7593dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7603dec9fcdSqs "ddi_map_regs for Hydra global reg failed")); 7613dec9fcdSqs goto hxge_map_regs_fail1; 7623dec9fcdSqs } 7633dec9fcdSqs 7643dec9fcdSqs /* set up the msi/msi-x mapped register */ 7653dec9fcdSqs (void) ddi_dev_regsize(hxgep->dip, 2, ®size); 7663dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 7673dec9fcdSqs "hxge_map_regs: msix size 0x%x", regsize)); 7683dec9fcdSqs 7693dec9fcdSqs ddi_status = ddi_regs_map_setup(hxgep->dip, 2, 7703dec9fcdSqs (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0, 7713dec9fcdSqs &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh); 7723dec9fcdSqs 7733dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 7743dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7753dec9fcdSqs "ddi_map_regs for msi reg failed")); 7763dec9fcdSqs goto hxge_map_regs_fail2; 7773dec9fcdSqs } 7783dec9fcdSqs 7793dec9fcdSqs hxgep->dev_regs = dev_regs; 7803dec9fcdSqs 7813dec9fcdSqs HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh); 7823dec9fcdSqs HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp); 7833dec9fcdSqs HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh); 7843dec9fcdSqs HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp); 7853dec9fcdSqs 7863dec9fcdSqs HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 7873dec9fcdSqs HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 7883dec9fcdSqs 7893dec9fcdSqs HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 7903dec9fcdSqs HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 7913dec9fcdSqs 7923dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx " 7933dec9fcdSqs " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh)); 7943dec9fcdSqs 7953dec9fcdSqs goto hxge_map_regs_exit; 7963dec9fcdSqs 7973dec9fcdSqs hxge_map_regs_fail3: 7983dec9fcdSqs if (dev_regs->hxge_msix_regh) { 7993dec9fcdSqs ddi_regs_map_free(&dev_regs->hxge_msix_regh); 8003dec9fcdSqs } 8013dec9fcdSqs 8023dec9fcdSqs hxge_map_regs_fail2: 8033dec9fcdSqs if (dev_regs->hxge_regh) { 8043dec9fcdSqs ddi_regs_map_free(&dev_regs->hxge_regh); 8053dec9fcdSqs } 8063dec9fcdSqs 8073dec9fcdSqs hxge_map_regs_fail1: 8083dec9fcdSqs if (dev_regs->hxge_pciregh) { 8093dec9fcdSqs ddi_regs_map_free(&dev_regs->hxge_pciregh); 8103dec9fcdSqs } 8113dec9fcdSqs 8123dec9fcdSqs hxge_map_regs_fail0: 8133dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory")); 8143dec9fcdSqs kmem_free(dev_regs, sizeof (dev_regs_t)); 8153dec9fcdSqs 8163dec9fcdSqs hxge_map_regs_exit: 8173dec9fcdSqs if (ddi_status != DDI_SUCCESS) 8183dec9fcdSqs status |= (HXGE_ERROR | HXGE_DDI_FAILED); 8193dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs")); 8203dec9fcdSqs return (status); 8213dec9fcdSqs } 8223dec9fcdSqs 8233dec9fcdSqs static void 8243dec9fcdSqs hxge_unmap_regs(p_hxge_t hxgep) 8253dec9fcdSqs { 8263dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs")); 8273dec9fcdSqs if (hxgep->dev_regs) { 8283dec9fcdSqs if (hxgep->dev_regs->hxge_pciregh) { 8293dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8303dec9fcdSqs "==> hxge_unmap_regs: bus")); 8313dec9fcdSqs ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh); 8323dec9fcdSqs hxgep->dev_regs->hxge_pciregh = NULL; 8333dec9fcdSqs } 8343dec9fcdSqs 8353dec9fcdSqs if (hxgep->dev_regs->hxge_regh) { 8363dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8373dec9fcdSqs "==> hxge_unmap_regs: device registers")); 8383dec9fcdSqs ddi_regs_map_free(&hxgep->dev_regs->hxge_regh); 8393dec9fcdSqs hxgep->dev_regs->hxge_regh = NULL; 8403dec9fcdSqs } 8413dec9fcdSqs 8423dec9fcdSqs if (hxgep->dev_regs->hxge_msix_regh) { 8433dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8443dec9fcdSqs "==> hxge_unmap_regs: device interrupts")); 8453dec9fcdSqs ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh); 8463dec9fcdSqs hxgep->dev_regs->hxge_msix_regh = NULL; 8473dec9fcdSqs } 8483dec9fcdSqs kmem_free(hxgep->dev_regs, sizeof (dev_regs_t)); 8493dec9fcdSqs hxgep->dev_regs = NULL; 8503dec9fcdSqs } 8513dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs")); 8523dec9fcdSqs } 8533dec9fcdSqs 8543dec9fcdSqs static hxge_status_t 8553dec9fcdSqs hxge_setup_mutexes(p_hxge_t hxgep) 8563dec9fcdSqs { 8573dec9fcdSqs int ddi_status = DDI_SUCCESS; 8583dec9fcdSqs hxge_status_t status = HXGE_OK; 8593dec9fcdSqs 8603dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes")); 8613dec9fcdSqs 8623dec9fcdSqs /* 8633dec9fcdSqs * Get the interrupt cookie so the mutexes can be Initialised. 8643dec9fcdSqs */ 8653dec9fcdSqs ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0, 8663dec9fcdSqs &hxgep->interrupt_cookie); 8673dec9fcdSqs 8683dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 8693dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8703dec9fcdSqs "<== hxge_setup_mutexes: failed 0x%x", ddi_status)); 8713dec9fcdSqs goto hxge_setup_mutexes_exit; 8723dec9fcdSqs } 8733dec9fcdSqs 8743dec9fcdSqs /* 8753dec9fcdSqs * Initialize mutex's for this device. 8763dec9fcdSqs */ 8773dec9fcdSqs MUTEX_INIT(hxgep->genlock, NULL, 8783dec9fcdSqs MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 8793dec9fcdSqs MUTEX_INIT(&hxgep->ouraddr_lock, NULL, 8803dec9fcdSqs MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 8813dec9fcdSqs RW_INIT(&hxgep->filter_lock, NULL, 8823dec9fcdSqs RW_DRIVER, (void *) hxgep->interrupt_cookie); 883fe930412Sqs MUTEX_INIT(&hxgep->pio_lock, NULL, 884fe930412Sqs MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 885*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_INIT(&hxgep->timeout.lock, NULL, 886*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 8873dec9fcdSqs 8883dec9fcdSqs hxge_setup_mutexes_exit: 8893dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 8903dec9fcdSqs "<== hxge_setup_mutexes status = %x", status)); 8913dec9fcdSqs 8923dec9fcdSqs if (ddi_status != DDI_SUCCESS) 8933dec9fcdSqs status |= (HXGE_ERROR | HXGE_DDI_FAILED); 8943dec9fcdSqs 8953dec9fcdSqs return (status); 8963dec9fcdSqs } 8973dec9fcdSqs 8983dec9fcdSqs static void 8993dec9fcdSqs hxge_destroy_mutexes(p_hxge_t hxgep) 9003dec9fcdSqs { 9013dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes")); 9023dec9fcdSqs RW_DESTROY(&hxgep->filter_lock); 9033dec9fcdSqs MUTEX_DESTROY(&hxgep->ouraddr_lock); 9043dec9fcdSqs MUTEX_DESTROY(hxgep->genlock); 905fe930412Sqs MUTEX_DESTROY(&hxgep->pio_lock); 906*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_DESTROY(&hxgep->timeout.lock); 9073dec9fcdSqs 9083dec9fcdSqs if (hxge_debug_init == 1) { 9093dec9fcdSqs MUTEX_DESTROY(&hxgedebuglock); 9103dec9fcdSqs hxge_debug_init = 0; 9113dec9fcdSqs } 9123dec9fcdSqs 9133dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes")); 9143dec9fcdSqs } 9153dec9fcdSqs 9163dec9fcdSqs hxge_status_t 9173dec9fcdSqs hxge_init(p_hxge_t hxgep) 9183dec9fcdSqs { 9193dec9fcdSqs hxge_status_t status = HXGE_OK; 9203dec9fcdSqs 9213dec9fcdSqs HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init")); 9223dec9fcdSqs 9233dec9fcdSqs if (hxgep->drv_state & STATE_HW_INITIALIZED) { 9243dec9fcdSqs return (status); 9253dec9fcdSqs } 9263dec9fcdSqs 9273dec9fcdSqs /* 9283dec9fcdSqs * Allocate system memory for the receive/transmit buffer blocks and 9293dec9fcdSqs * receive/transmit descriptor rings. 9303dec9fcdSqs */ 9313dec9fcdSqs status = hxge_alloc_mem_pool(hxgep); 9323dec9fcdSqs if (status != HXGE_OK) { 9333dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n")); 9343dec9fcdSqs goto hxge_init_fail1; 9353dec9fcdSqs } 9363dec9fcdSqs 9373dec9fcdSqs /* 9383dec9fcdSqs * Initialize and enable TXDMA channels. 9393dec9fcdSqs */ 9403dec9fcdSqs status = hxge_init_txdma_channels(hxgep); 9413dec9fcdSqs if (status != HXGE_OK) { 9423dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n")); 9433dec9fcdSqs goto hxge_init_fail3; 9443dec9fcdSqs } 9453dec9fcdSqs 9463dec9fcdSqs /* 9473dec9fcdSqs * Initialize and enable RXDMA channels. 9483dec9fcdSqs */ 9493dec9fcdSqs status = hxge_init_rxdma_channels(hxgep); 9503dec9fcdSqs if (status != HXGE_OK) { 9513dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n")); 9523dec9fcdSqs goto hxge_init_fail4; 9533dec9fcdSqs } 9543dec9fcdSqs 9553dec9fcdSqs /* 9563dec9fcdSqs * Initialize TCAM 9573dec9fcdSqs */ 9583dec9fcdSqs status = hxge_classify_init(hxgep); 9593dec9fcdSqs if (status != HXGE_OK) { 9603dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n")); 9613dec9fcdSqs goto hxge_init_fail5; 9623dec9fcdSqs } 9633dec9fcdSqs 9643dec9fcdSqs /* 9653dec9fcdSqs * Initialize the VMAC block. 9663dec9fcdSqs */ 9673dec9fcdSqs status = hxge_vmac_init(hxgep); 9683dec9fcdSqs if (status != HXGE_OK) { 9693dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n")); 9703dec9fcdSqs goto hxge_init_fail5; 9713dec9fcdSqs } 9723dec9fcdSqs 9733dec9fcdSqs /* Bringup - this may be unnecessary when PXE and FCODE available */ 9743dec9fcdSqs status = hxge_pfc_set_default_mac_addr(hxgep); 9753dec9fcdSqs if (status != HXGE_OK) { 9763dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9773dec9fcdSqs "Default Address Failure\n")); 9783dec9fcdSqs goto hxge_init_fail5; 9793dec9fcdSqs } 9803dec9fcdSqs 9813dec9fcdSqs hxge_intrs_enable(hxgep); 9823dec9fcdSqs 9833dec9fcdSqs /* 9843dec9fcdSqs * Enable hardware interrupts. 9853dec9fcdSqs */ 9863dec9fcdSqs hxge_intr_hw_enable(hxgep); 9873dec9fcdSqs hxgep->drv_state |= STATE_HW_INITIALIZED; 9883dec9fcdSqs 9893dec9fcdSqs goto hxge_init_exit; 9903dec9fcdSqs 9913dec9fcdSqs hxge_init_fail5: 9923dec9fcdSqs hxge_uninit_rxdma_channels(hxgep); 9933dec9fcdSqs hxge_init_fail4: 9943dec9fcdSqs hxge_uninit_txdma_channels(hxgep); 9953dec9fcdSqs hxge_init_fail3: 9963dec9fcdSqs hxge_free_mem_pool(hxgep); 9973dec9fcdSqs hxge_init_fail1: 9983dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9993dec9fcdSqs "<== hxge_init status (failed) = 0x%08x", status)); 10003dec9fcdSqs return (status); 10013dec9fcdSqs 10023dec9fcdSqs hxge_init_exit: 10033dec9fcdSqs 10043dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x", 10053dec9fcdSqs status)); 10063dec9fcdSqs 10073dec9fcdSqs return (status); 10083dec9fcdSqs } 10093dec9fcdSqs 10103dec9fcdSqs timeout_id_t 10113dec9fcdSqs hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec) 10123dec9fcdSqs { 10133dec9fcdSqs if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) { 10143dec9fcdSqs return (timeout(func, (caddr_t)hxgep, 10153dec9fcdSqs drv_usectohz(1000 * msec))); 10163dec9fcdSqs } 10173dec9fcdSqs return (NULL); 10183dec9fcdSqs } 10193dec9fcdSqs 10203dec9fcdSqs /*ARGSUSED*/ 10213dec9fcdSqs void 10223dec9fcdSqs hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid) 10233dec9fcdSqs { 10243dec9fcdSqs if (timerid) { 10253dec9fcdSqs (void) untimeout(timerid); 10263dec9fcdSqs } 10273dec9fcdSqs } 10283dec9fcdSqs 10293dec9fcdSqs void 10303dec9fcdSqs hxge_uninit(p_hxge_t hxgep) 10313dec9fcdSqs { 10323dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit")); 10333dec9fcdSqs 10343dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 10353dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 10363dec9fcdSqs "==> hxge_uninit: not initialized")); 10373dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 10383dec9fcdSqs return; 10393dec9fcdSqs } 10403dec9fcdSqs 10413dec9fcdSqs /* Stop timer */ 10423dec9fcdSqs if (hxgep->hxge_timerid) { 10433dec9fcdSqs hxge_stop_timer(hxgep, hxgep->hxge_timerid); 10443dec9fcdSqs hxgep->hxge_timerid = 0; 10453dec9fcdSqs } 10463dec9fcdSqs 10473dec9fcdSqs (void) hxge_intr_hw_disable(hxgep); 10483dec9fcdSqs 10493dec9fcdSqs /* Reset the receive VMAC side. */ 10503dec9fcdSqs (void) hxge_rx_vmac_disable(hxgep); 10513dec9fcdSqs 10523dec9fcdSqs /* Free classification resources */ 10533dec9fcdSqs (void) hxge_classify_uninit(hxgep); 10543dec9fcdSqs 10553dec9fcdSqs /* Reset the transmit/receive DMA side. */ 10563dec9fcdSqs (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP); 10573dec9fcdSqs (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP); 10583dec9fcdSqs 10593dec9fcdSqs hxge_uninit_txdma_channels(hxgep); 10603dec9fcdSqs hxge_uninit_rxdma_channels(hxgep); 10613dec9fcdSqs 10623dec9fcdSqs /* Reset the transmit VMAC side. */ 10633dec9fcdSqs (void) hxge_tx_vmac_disable(hxgep); 10643dec9fcdSqs 10653dec9fcdSqs hxge_free_mem_pool(hxgep); 10663dec9fcdSqs 10673dec9fcdSqs hxgep->drv_state &= ~STATE_HW_INITIALIZED; 10683dec9fcdSqs 10693dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 10703dec9fcdSqs } 10713dec9fcdSqs 10723dec9fcdSqs void 10733dec9fcdSqs hxge_get64(p_hxge_t hxgep, p_mblk_t mp) 10743dec9fcdSqs { 10753dec9fcdSqs #if defined(__i386) 10763dec9fcdSqs size_t reg; 10773dec9fcdSqs #else 10783dec9fcdSqs uint64_t reg; 10793dec9fcdSqs #endif 10803dec9fcdSqs uint64_t regdata; 10813dec9fcdSqs int i, retry; 10823dec9fcdSqs 10833dec9fcdSqs bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 10843dec9fcdSqs regdata = 0; 10853dec9fcdSqs retry = 1; 10863dec9fcdSqs 10873dec9fcdSqs for (i = 0; i < retry; i++) { 10883dec9fcdSqs HXGE_REG_RD64(hxgep->hpi_handle, reg, ®data); 10893dec9fcdSqs } 10903dec9fcdSqs bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 10913dec9fcdSqs } 10923dec9fcdSqs 10933dec9fcdSqs void 10943dec9fcdSqs hxge_put64(p_hxge_t hxgep, p_mblk_t mp) 10953dec9fcdSqs { 10963dec9fcdSqs #if defined(__i386) 10973dec9fcdSqs size_t reg; 10983dec9fcdSqs #else 10993dec9fcdSqs uint64_t reg; 11003dec9fcdSqs #endif 11013dec9fcdSqs uint64_t buf[2]; 11023dec9fcdSqs 11033dec9fcdSqs bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 11043dec9fcdSqs #if defined(__i386) 11053dec9fcdSqs reg = (size_t)buf[0]; 11063dec9fcdSqs #else 11073dec9fcdSqs reg = buf[0]; 11083dec9fcdSqs #endif 11093dec9fcdSqs 11103dec9fcdSqs HXGE_HPI_PIO_WRITE64(hxgep->hpi_handle, reg, buf[1]); 11113dec9fcdSqs } 11123dec9fcdSqs 11133dec9fcdSqs /*ARGSUSED*/ 11143dec9fcdSqs /*VARARGS*/ 11153dec9fcdSqs void 11163dec9fcdSqs hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...) 11173dec9fcdSqs { 11183dec9fcdSqs char msg_buffer[1048]; 11193dec9fcdSqs char prefix_buffer[32]; 11203dec9fcdSqs int instance; 11213dec9fcdSqs uint64_t debug_level; 11223dec9fcdSqs int cmn_level = CE_CONT; 11233dec9fcdSqs va_list ap; 11243dec9fcdSqs 11253dec9fcdSqs debug_level = (hxgep == NULL) ? hxge_debug_level : 11263dec9fcdSqs hxgep->hxge_debug_level; 11273dec9fcdSqs 11283dec9fcdSqs if ((level & debug_level) || (level == HXGE_NOTE) || 11293dec9fcdSqs (level == HXGE_ERR_CTL)) { 11303dec9fcdSqs /* do the msg processing */ 11313dec9fcdSqs if (hxge_debug_init == 0) { 11323dec9fcdSqs MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL); 11333dec9fcdSqs hxge_debug_init = 1; 11343dec9fcdSqs } 11353dec9fcdSqs 11363dec9fcdSqs MUTEX_ENTER(&hxgedebuglock); 11373dec9fcdSqs 11383dec9fcdSqs if ((level & HXGE_NOTE)) { 11393dec9fcdSqs cmn_level = CE_NOTE; 11403dec9fcdSqs } 11413dec9fcdSqs 11423dec9fcdSqs if (level & HXGE_ERR_CTL) { 11433dec9fcdSqs cmn_level = CE_WARN; 11443dec9fcdSqs } 11453dec9fcdSqs 11463dec9fcdSqs va_start(ap, fmt); 11473dec9fcdSqs (void) vsprintf(msg_buffer, fmt, ap); 11483dec9fcdSqs va_end(ap); 11493dec9fcdSqs 11503dec9fcdSqs if (hxgep == NULL) { 11513dec9fcdSqs instance = -1; 11523dec9fcdSqs (void) sprintf(prefix_buffer, "%s :", "hxge"); 11533dec9fcdSqs } else { 11543dec9fcdSqs instance = hxgep->instance; 11553dec9fcdSqs (void) sprintf(prefix_buffer, 11563dec9fcdSqs "%s%d :", "hxge", instance); 11573dec9fcdSqs } 11583dec9fcdSqs 11593dec9fcdSqs MUTEX_EXIT(&hxgedebuglock); 11603dec9fcdSqs cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer); 11613dec9fcdSqs } 11623dec9fcdSqs } 11633dec9fcdSqs 11643dec9fcdSqs char * 11653dec9fcdSqs hxge_dump_packet(char *addr, int size) 11663dec9fcdSqs { 11673dec9fcdSqs uchar_t *ap = (uchar_t *)addr; 11683dec9fcdSqs int i; 11693dec9fcdSqs static char etherbuf[1024]; 11703dec9fcdSqs char *cp = etherbuf; 11713dec9fcdSqs char digits[] = "0123456789abcdef"; 11723dec9fcdSqs 11733dec9fcdSqs if (!size) 11743dec9fcdSqs size = 60; 11753dec9fcdSqs 11763dec9fcdSqs if (size > MAX_DUMP_SZ) { 11773dec9fcdSqs /* Dump the leading bytes */ 11783dec9fcdSqs for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 11793dec9fcdSqs if (*ap > 0x0f) 11803dec9fcdSqs *cp++ = digits[*ap >> 4]; 11813dec9fcdSqs *cp++ = digits[*ap++ & 0xf]; 11823dec9fcdSqs *cp++ = ':'; 11833dec9fcdSqs } 11843dec9fcdSqs for (i = 0; i < 20; i++) 11853dec9fcdSqs *cp++ = '.'; 11863dec9fcdSqs /* Dump the last MAX_DUMP_SZ/2 bytes */ 11873dec9fcdSqs ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2)); 11883dec9fcdSqs for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 11893dec9fcdSqs if (*ap > 0x0f) 11903dec9fcdSqs *cp++ = digits[*ap >> 4]; 11913dec9fcdSqs *cp++ = digits[*ap++ & 0xf]; 11923dec9fcdSqs *cp++ = ':'; 11933dec9fcdSqs } 11943dec9fcdSqs } else { 11953dec9fcdSqs for (i = 0; i < size; i++) { 11963dec9fcdSqs if (*ap > 0x0f) 11973dec9fcdSqs *cp++ = digits[*ap >> 4]; 11983dec9fcdSqs *cp++ = digits[*ap++ & 0xf]; 11993dec9fcdSqs *cp++ = ':'; 12003dec9fcdSqs } 12013dec9fcdSqs } 12023dec9fcdSqs *--cp = 0; 12033dec9fcdSqs return (etherbuf); 12043dec9fcdSqs } 12053dec9fcdSqs 12063dec9fcdSqs static void 12073dec9fcdSqs hxge_suspend(p_hxge_t hxgep) 12083dec9fcdSqs { 12093dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend")); 12103dec9fcdSqs 12113dec9fcdSqs hxge_intrs_disable(hxgep); 12123dec9fcdSqs hxge_destroy_dev(hxgep); 12133dec9fcdSqs 1214*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Stop the link status timer */ 1215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&hxgep->timeout.lock); 1216*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (hxgep->timeout.id) 1217*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) untimeout(hxgep->timeout.id); 1218*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&hxgep->timeout.lock); 1219*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 12203dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend")); 12213dec9fcdSqs } 12223dec9fcdSqs 12233dec9fcdSqs static hxge_status_t 12243dec9fcdSqs hxge_resume(p_hxge_t hxgep) 12253dec9fcdSqs { 12263dec9fcdSqs hxge_status_t status = HXGE_OK; 12273dec9fcdSqs 12283dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume")); 12293dec9fcdSqs hxgep->suspended = DDI_RESUME; 12303dec9fcdSqs 12313dec9fcdSqs (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START); 12323dec9fcdSqs (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START); 12333dec9fcdSqs 12343dec9fcdSqs (void) hxge_rx_vmac_enable(hxgep); 12353dec9fcdSqs (void) hxge_tx_vmac_enable(hxgep); 12363dec9fcdSqs 12373dec9fcdSqs hxge_intrs_enable(hxgep); 12383dec9fcdSqs 12393dec9fcdSqs hxgep->suspended = 0; 12403dec9fcdSqs 1241*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Resume the link status timer */ 1242*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&hxgep->timeout.lock); 1243*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 1244*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->timeout.ticks); 1245*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&hxgep->timeout.lock); 1246*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 12473dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 12483dec9fcdSqs "<== hxge_resume status = 0x%x", status)); 12493dec9fcdSqs 12503dec9fcdSqs return (status); 12513dec9fcdSqs } 12523dec9fcdSqs 12533dec9fcdSqs hxge_status_t 12543dec9fcdSqs hxge_setup_dev(p_hxge_t hxgep) 12553dec9fcdSqs { 12563dec9fcdSqs hxge_status_t status = HXGE_OK; 12573dec9fcdSqs 12583dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev")); 12593dec9fcdSqs 12603dec9fcdSqs status = hxge_link_init(hxgep); 12613dec9fcdSqs if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) { 12623dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 12633dec9fcdSqs "Bad register acc handle")); 12643dec9fcdSqs status = HXGE_ERROR; 12653dec9fcdSqs } 12663dec9fcdSqs 12673dec9fcdSqs if (status != HXGE_OK) { 12683dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, 12693dec9fcdSqs " hxge_setup_dev status (link init 0x%08x)", status)); 12703dec9fcdSqs goto hxge_setup_dev_exit; 12713dec9fcdSqs } 12723dec9fcdSqs 12733dec9fcdSqs hxge_setup_dev_exit: 12743dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 12753dec9fcdSqs "<== hxge_setup_dev status = 0x%08x", status)); 12763dec9fcdSqs 12773dec9fcdSqs return (status); 12783dec9fcdSqs } 12793dec9fcdSqs 12803dec9fcdSqs static void 12813dec9fcdSqs hxge_destroy_dev(p_hxge_t hxgep) 12823dec9fcdSqs { 12833dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev")); 12843dec9fcdSqs 12853dec9fcdSqs (void) hxge_hw_stop(hxgep); 12863dec9fcdSqs 12873dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev")); 12883dec9fcdSqs } 12893dec9fcdSqs 12903dec9fcdSqs static hxge_status_t 12913dec9fcdSqs hxge_setup_system_dma_pages(p_hxge_t hxgep) 12923dec9fcdSqs { 12933dec9fcdSqs int ddi_status = DDI_SUCCESS; 12943dec9fcdSqs uint_t count; 12953dec9fcdSqs ddi_dma_cookie_t cookie; 12963dec9fcdSqs uint_t iommu_pagesize; 12973dec9fcdSqs hxge_status_t status = HXGE_OK; 12983dec9fcdSqs 12993dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages")); 13003dec9fcdSqs 13013dec9fcdSqs hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1); 13023dec9fcdSqs iommu_pagesize = dvma_pagesize(hxgep->dip); 13033dec9fcdSqs 13043dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13053dec9fcdSqs " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 13063dec9fcdSqs " default_block_size %d iommu_pagesize %d", 13073dec9fcdSqs hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 13083dec9fcdSqs hxgep->rx_default_block_size, iommu_pagesize)); 13093dec9fcdSqs 13103dec9fcdSqs if (iommu_pagesize != 0) { 13113dec9fcdSqs if (hxgep->sys_page_sz == iommu_pagesize) { 13123dec9fcdSqs /* Hydra support up to 8K pages */ 13133dec9fcdSqs if (iommu_pagesize > 0x2000) 13143dec9fcdSqs hxgep->sys_page_sz = 0x2000; 13153dec9fcdSqs } else { 13163dec9fcdSqs if (hxgep->sys_page_sz > iommu_pagesize) 13173dec9fcdSqs hxgep->sys_page_sz = iommu_pagesize; 13183dec9fcdSqs } 13193dec9fcdSqs } 13203dec9fcdSqs 13213dec9fcdSqs hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 13223dec9fcdSqs 13233dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13243dec9fcdSqs "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 13253dec9fcdSqs "default_block_size %d page mask %d", 13263dec9fcdSqs hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 13273dec9fcdSqs hxgep->rx_default_block_size, hxgep->sys_page_mask)); 13283dec9fcdSqs 13293dec9fcdSqs switch (hxgep->sys_page_sz) { 13303dec9fcdSqs default: 13313dec9fcdSqs hxgep->sys_page_sz = 0x1000; 13323dec9fcdSqs hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 13333dec9fcdSqs hxgep->rx_default_block_size = 0x1000; 13343dec9fcdSqs hxgep->rx_bksize_code = RBR_BKSIZE_4K; 13353dec9fcdSqs break; 13363dec9fcdSqs case 0x1000: 13373dec9fcdSqs hxgep->rx_default_block_size = 0x1000; 13383dec9fcdSqs hxgep->rx_bksize_code = RBR_BKSIZE_4K; 13393dec9fcdSqs break; 13403dec9fcdSqs case 0x2000: 13413dec9fcdSqs hxgep->rx_default_block_size = 0x2000; 13423dec9fcdSqs hxgep->rx_bksize_code = RBR_BKSIZE_8K; 13433dec9fcdSqs break; 13443dec9fcdSqs } 13453dec9fcdSqs 13463dec9fcdSqs hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 13473dec9fcdSqs hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 13483dec9fcdSqs hxge_desc_dma_attr.dma_attr_align = hxgep->sys_page_sz; 13493dec9fcdSqs 13503dec9fcdSqs /* 13513dec9fcdSqs * Get the system DMA burst size. 13523dec9fcdSqs */ 13533dec9fcdSqs ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr, 13543dec9fcdSqs DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle); 13553dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 13563dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 13573dec9fcdSqs "ddi_dma_alloc_handle: failed status 0x%x", ddi_status)); 13583dec9fcdSqs goto hxge_get_soft_properties_exit; 13593dec9fcdSqs } 13603dec9fcdSqs 13613dec9fcdSqs ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL, 13623dec9fcdSqs (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle), 13633dec9fcdSqs DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0, 13643dec9fcdSqs &cookie, &count); 13653dec9fcdSqs if (ddi_status != DDI_DMA_MAPPED) { 13663dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 13673dec9fcdSqs "Binding spare handle to find system burstsize failed.")); 13683dec9fcdSqs ddi_status = DDI_FAILURE; 13693dec9fcdSqs goto hxge_get_soft_properties_fail1; 13703dec9fcdSqs } 13713dec9fcdSqs 13723dec9fcdSqs hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle); 13733dec9fcdSqs (void) ddi_dma_unbind_handle(hxgep->dmasparehandle); 13743dec9fcdSqs 13753dec9fcdSqs hxge_get_soft_properties_fail1: 13763dec9fcdSqs ddi_dma_free_handle(&hxgep->dmasparehandle); 13773dec9fcdSqs 13783dec9fcdSqs hxge_get_soft_properties_exit: 13793dec9fcdSqs 13803dec9fcdSqs if (ddi_status != DDI_SUCCESS) 13813dec9fcdSqs status |= (HXGE_ERROR | HXGE_DDI_FAILED); 13823dec9fcdSqs 13833dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 13843dec9fcdSqs "<== hxge_setup_system_dma_pages status = 0x%08x", status)); 13853dec9fcdSqs 13863dec9fcdSqs return (status); 13873dec9fcdSqs } 13883dec9fcdSqs 13893dec9fcdSqs hxge_status_t 13903dec9fcdSqs hxge_alloc_mem_pool(p_hxge_t hxgep) 13913dec9fcdSqs { 13923dec9fcdSqs hxge_status_t status = HXGE_OK; 13933dec9fcdSqs 13943dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool")); 13953dec9fcdSqs 13963dec9fcdSqs status = hxge_alloc_rx_mem_pool(hxgep); 13973dec9fcdSqs if (status != HXGE_OK) { 13983dec9fcdSqs return (HXGE_ERROR); 13993dec9fcdSqs } 14003dec9fcdSqs 14013dec9fcdSqs status = hxge_alloc_tx_mem_pool(hxgep); 14023dec9fcdSqs if (status != HXGE_OK) { 14033dec9fcdSqs hxge_free_rx_mem_pool(hxgep); 14043dec9fcdSqs return (HXGE_ERROR); 14053dec9fcdSqs } 14063dec9fcdSqs 14073dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool")); 14083dec9fcdSqs return (HXGE_OK); 14093dec9fcdSqs } 14103dec9fcdSqs 14113dec9fcdSqs static void 14123dec9fcdSqs hxge_free_mem_pool(p_hxge_t hxgep) 14133dec9fcdSqs { 14143dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool")); 14153dec9fcdSqs 14163dec9fcdSqs hxge_free_rx_mem_pool(hxgep); 14173dec9fcdSqs hxge_free_tx_mem_pool(hxgep); 14183dec9fcdSqs 14193dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool")); 14203dec9fcdSqs } 14213dec9fcdSqs 14223dec9fcdSqs static hxge_status_t 14233dec9fcdSqs hxge_alloc_rx_mem_pool(p_hxge_t hxgep) 14243dec9fcdSqs { 14253dec9fcdSqs int i, j; 14263dec9fcdSqs uint32_t ndmas, st_rdc; 14273dec9fcdSqs p_hxge_dma_pt_cfg_t p_all_cfgp; 14283dec9fcdSqs p_hxge_hw_pt_cfg_t p_cfgp; 14293dec9fcdSqs p_hxge_dma_pool_t dma_poolp; 14303dec9fcdSqs p_hxge_dma_common_t *dma_buf_p; 14313dec9fcdSqs p_hxge_dma_pool_t dma_cntl_poolp; 14323dec9fcdSqs p_hxge_dma_common_t *dma_cntl_p; 14333dec9fcdSqs size_t rx_buf_alloc_size; 14343dec9fcdSqs size_t rx_cntl_alloc_size; 14353dec9fcdSqs uint32_t *num_chunks; /* per dma */ 14363dec9fcdSqs hxge_status_t status = HXGE_OK; 14373dec9fcdSqs 14383dec9fcdSqs uint32_t hxge_port_rbr_size; 14393dec9fcdSqs uint32_t hxge_port_rbr_spare_size; 14403dec9fcdSqs uint32_t hxge_port_rcr_size; 14413dec9fcdSqs 14423dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool")); 14433dec9fcdSqs 14443dec9fcdSqs p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 14453dec9fcdSqs p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 14463dec9fcdSqs st_rdc = p_cfgp->start_rdc; 14473dec9fcdSqs ndmas = p_cfgp->max_rdcs; 14483dec9fcdSqs 14493dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 14503dec9fcdSqs " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 14513dec9fcdSqs 14523dec9fcdSqs /* 14533dec9fcdSqs * Allocate memory for each receive DMA channel. 14543dec9fcdSqs */ 14553dec9fcdSqs dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 14563dec9fcdSqs KM_SLEEP); 14573dec9fcdSqs dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 14583dec9fcdSqs sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 14593dec9fcdSqs 14603dec9fcdSqs dma_cntl_poolp = (p_hxge_dma_pool_t) 14613dec9fcdSqs KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 14623dec9fcdSqs dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 14633dec9fcdSqs sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 14643dec9fcdSqs 14653dec9fcdSqs num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 14663dec9fcdSqs KM_SLEEP); 14673dec9fcdSqs 14683dec9fcdSqs /* 14693dec9fcdSqs * Assume that each DMA channel will be configured with default block 14703dec9fcdSqs * size. rbr block counts are mod of batch count (16). 14713dec9fcdSqs */ 14723dec9fcdSqs hxge_port_rbr_size = p_all_cfgp->rbr_size; 14733dec9fcdSqs hxge_port_rcr_size = p_all_cfgp->rcr_size; 14743dec9fcdSqs 14753dec9fcdSqs if (!hxge_port_rbr_size) { 14763dec9fcdSqs hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT; 14773dec9fcdSqs } 14783dec9fcdSqs 14793dec9fcdSqs if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) { 14803dec9fcdSqs hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH * 14813dec9fcdSqs (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1)); 14823dec9fcdSqs } 14833dec9fcdSqs 14843dec9fcdSqs p_all_cfgp->rbr_size = hxge_port_rbr_size; 14853dec9fcdSqs hxge_port_rbr_spare_size = hxge_rbr_spare_size; 14863dec9fcdSqs 14873dec9fcdSqs if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) { 14883dec9fcdSqs hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH * 14893dec9fcdSqs (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1)); 14903dec9fcdSqs } 14913dec9fcdSqs 14923dec9fcdSqs rx_buf_alloc_size = (hxgep->rx_default_block_size * 14933dec9fcdSqs (hxge_port_rbr_size + hxge_port_rbr_spare_size)); 14943dec9fcdSqs 14953dec9fcdSqs /* 14963dec9fcdSqs * Addresses of receive block ring, receive completion ring and the 14973dec9fcdSqs * mailbox must be all cache-aligned (64 bytes). 14983dec9fcdSqs */ 14993dec9fcdSqs rx_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size; 15003dec9fcdSqs rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 15013dec9fcdSqs rx_cntl_alloc_size += (sizeof (rcr_entry_t) * hxge_port_rcr_size); 15023dec9fcdSqs rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 15033dec9fcdSqs 15043dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: " 15053dec9fcdSqs "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d " 15063dec9fcdSqs "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d", 15073dec9fcdSqs hxge_port_rbr_size, hxge_port_rbr_spare_size, 15083dec9fcdSqs hxge_port_rcr_size, rx_cntl_alloc_size)); 15093dec9fcdSqs 15103dec9fcdSqs hxgep->hxge_port_rbr_size = hxge_port_rbr_size; 15113dec9fcdSqs hxgep->hxge_port_rcr_size = hxge_port_rcr_size; 15123dec9fcdSqs 15133dec9fcdSqs /* 15143dec9fcdSqs * Allocate memory for receive buffers and descriptor rings. Replace 15153dec9fcdSqs * allocation functions with interface functions provided by the 15163dec9fcdSqs * partition manager when it is available. 15173dec9fcdSqs */ 15183dec9fcdSqs /* 15193dec9fcdSqs * Allocate memory for the receive buffer blocks. 15203dec9fcdSqs */ 15213dec9fcdSqs for (i = 0; i < ndmas; i++) { 15223dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 15233dec9fcdSqs " hxge_alloc_rx_mem_pool to alloc mem: " 15243dec9fcdSqs " dma %d dma_buf_p %llx &dma_buf_p %llx", 15253dec9fcdSqs i, dma_buf_p[i], &dma_buf_p[i])); 15263dec9fcdSqs 15273dec9fcdSqs num_chunks[i] = 0; 15283dec9fcdSqs 15293dec9fcdSqs status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i], 15303dec9fcdSqs rx_buf_alloc_size, hxgep->rx_default_block_size, 15313dec9fcdSqs &num_chunks[i]); 15323dec9fcdSqs if (status != HXGE_OK) { 15333dec9fcdSqs break; 15343dec9fcdSqs } 15353dec9fcdSqs 15363dec9fcdSqs st_rdc++; 15373dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 15383dec9fcdSqs " hxge_alloc_rx_mem_pool DONE alloc mem: " 15393dec9fcdSqs "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 15403dec9fcdSqs dma_buf_p[i], &dma_buf_p[i])); 15413dec9fcdSqs } 15423dec9fcdSqs 15433dec9fcdSqs if (i < ndmas) { 15443dec9fcdSqs goto hxge_alloc_rx_mem_fail1; 15453dec9fcdSqs } 15463dec9fcdSqs 15473dec9fcdSqs /* 15483dec9fcdSqs * Allocate memory for descriptor rings and mailbox. 15493dec9fcdSqs */ 15503dec9fcdSqs st_rdc = p_cfgp->start_rdc; 15513dec9fcdSqs for (j = 0; j < ndmas; j++) { 15523dec9fcdSqs status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, &dma_cntl_p[j], 15533dec9fcdSqs rx_cntl_alloc_size); 15543dec9fcdSqs if (status != HXGE_OK) { 15553dec9fcdSqs break; 15563dec9fcdSqs } 15573dec9fcdSqs st_rdc++; 15583dec9fcdSqs } 15593dec9fcdSqs 15603dec9fcdSqs if (j < ndmas) { 15613dec9fcdSqs goto hxge_alloc_rx_mem_fail2; 15623dec9fcdSqs } 15633dec9fcdSqs 15643dec9fcdSqs dma_poolp->ndmas = ndmas; 15653dec9fcdSqs dma_poolp->num_chunks = num_chunks; 15663dec9fcdSqs dma_poolp->buf_allocated = B_TRUE; 15673dec9fcdSqs hxgep->rx_buf_pool_p = dma_poolp; 15683dec9fcdSqs dma_poolp->dma_buf_pool_p = dma_buf_p; 15693dec9fcdSqs 15703dec9fcdSqs dma_cntl_poolp->ndmas = ndmas; 15713dec9fcdSqs dma_cntl_poolp->buf_allocated = B_TRUE; 15723dec9fcdSqs hxgep->rx_cntl_pool_p = dma_cntl_poolp; 15733dec9fcdSqs dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 15743dec9fcdSqs 15753dec9fcdSqs goto hxge_alloc_rx_mem_pool_exit; 15763dec9fcdSqs 15773dec9fcdSqs hxge_alloc_rx_mem_fail2: 15783dec9fcdSqs /* Free control buffers */ 15793dec9fcdSqs j--; 15803dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 15813dec9fcdSqs "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 15823dec9fcdSqs for (; j >= 0; j--) { 15833dec9fcdSqs hxge_free_rx_cntl_dma(hxgep, 15843dec9fcdSqs (p_hxge_dma_common_t)dma_cntl_p[j]); 15853dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 15863dec9fcdSqs "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 15873dec9fcdSqs } 15883dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 15893dec9fcdSqs "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 15903dec9fcdSqs 15913dec9fcdSqs hxge_alloc_rx_mem_fail1: 15923dec9fcdSqs /* Free data buffers */ 15933dec9fcdSqs i--; 15943dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 15953dec9fcdSqs "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 15963dec9fcdSqs for (; i >= 0; i--) { 15973dec9fcdSqs hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 15983dec9fcdSqs num_chunks[i]); 15993dec9fcdSqs } 16003dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16013dec9fcdSqs "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 16023dec9fcdSqs 16033dec9fcdSqs KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 16043dec9fcdSqs KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 16053dec9fcdSqs KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 16063dec9fcdSqs KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 16073dec9fcdSqs KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 16083dec9fcdSqs 16093dec9fcdSqs hxge_alloc_rx_mem_pool_exit: 16103dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 16113dec9fcdSqs "<== hxge_alloc_rx_mem_pool:status 0x%08x", status)); 16123dec9fcdSqs 16133dec9fcdSqs return (status); 16143dec9fcdSqs } 16153dec9fcdSqs 16163dec9fcdSqs static void 16173dec9fcdSqs hxge_free_rx_mem_pool(p_hxge_t hxgep) 16183dec9fcdSqs { 16193dec9fcdSqs uint32_t i, ndmas; 16203dec9fcdSqs p_hxge_dma_pool_t dma_poolp; 16213dec9fcdSqs p_hxge_dma_common_t *dma_buf_p; 16223dec9fcdSqs p_hxge_dma_pool_t dma_cntl_poolp; 16233dec9fcdSqs p_hxge_dma_common_t *dma_cntl_p; 16243dec9fcdSqs uint32_t *num_chunks; 16253dec9fcdSqs 16263dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool")); 16273dec9fcdSqs 16283dec9fcdSqs dma_poolp = hxgep->rx_buf_pool_p; 16293dec9fcdSqs if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 16303dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool " 16313dec9fcdSqs "(null rx buf pool or buf not allocated")); 16323dec9fcdSqs return; 16333dec9fcdSqs } 16343dec9fcdSqs 16353dec9fcdSqs dma_cntl_poolp = hxgep->rx_cntl_pool_p; 16363dec9fcdSqs if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 16373dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 16383dec9fcdSqs "<== hxge_free_rx_mem_pool " 16393dec9fcdSqs "(null rx cntl buf pool or cntl buf not allocated")); 16403dec9fcdSqs return; 16413dec9fcdSqs } 16423dec9fcdSqs 16433dec9fcdSqs dma_buf_p = dma_poolp->dma_buf_pool_p; 16443dec9fcdSqs num_chunks = dma_poolp->num_chunks; 16453dec9fcdSqs 16463dec9fcdSqs dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 16473dec9fcdSqs ndmas = dma_cntl_poolp->ndmas; 16483dec9fcdSqs 16493dec9fcdSqs for (i = 0; i < ndmas; i++) { 16503dec9fcdSqs hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 16513dec9fcdSqs } 16523dec9fcdSqs 16533dec9fcdSqs for (i = 0; i < ndmas; i++) { 16543dec9fcdSqs hxge_free_rx_cntl_dma(hxgep, dma_cntl_p[i]); 16553dec9fcdSqs } 16563dec9fcdSqs 16573dec9fcdSqs for (i = 0; i < ndmas; i++) { 16583dec9fcdSqs KMEM_FREE(dma_buf_p[i], 16593dec9fcdSqs sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 16603dec9fcdSqs KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t)); 16613dec9fcdSqs } 16623dec9fcdSqs 16633dec9fcdSqs KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 16643dec9fcdSqs KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 16653dec9fcdSqs KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 16663dec9fcdSqs KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 16673dec9fcdSqs KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 16683dec9fcdSqs 16693dec9fcdSqs hxgep->rx_buf_pool_p = NULL; 16703dec9fcdSqs hxgep->rx_cntl_pool_p = NULL; 16713dec9fcdSqs 16723dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool")); 16733dec9fcdSqs } 16743dec9fcdSqs 16753dec9fcdSqs static hxge_status_t 16763dec9fcdSqs hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 16773dec9fcdSqs p_hxge_dma_common_t *dmap, 16783dec9fcdSqs size_t alloc_size, size_t block_size, uint32_t *num_chunks) 16793dec9fcdSqs { 16803dec9fcdSqs p_hxge_dma_common_t rx_dmap; 16813dec9fcdSqs hxge_status_t status = HXGE_OK; 16823dec9fcdSqs size_t total_alloc_size; 16833dec9fcdSqs size_t allocated = 0; 16843dec9fcdSqs int i, size_index, array_size; 16853dec9fcdSqs 16863dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma")); 16873dec9fcdSqs 16883dec9fcdSqs rx_dmap = (p_hxge_dma_common_t) 16893dec9fcdSqs KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 16903dec9fcdSqs 16913dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 16923dec9fcdSqs " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 16933dec9fcdSqs dma_channel, alloc_size, block_size, dmap)); 16943dec9fcdSqs 16953dec9fcdSqs total_alloc_size = alloc_size; 16963dec9fcdSqs 16973dec9fcdSqs i = 0; 16983dec9fcdSqs size_index = 0; 16993dec9fcdSqs array_size = sizeof (alloc_sizes) / sizeof (size_t); 17003dec9fcdSqs while ((alloc_sizes[size_index] < alloc_size) && 17013dec9fcdSqs (size_index < array_size)) 17023dec9fcdSqs size_index++; 17033dec9fcdSqs if (size_index >= array_size) { 17043dec9fcdSqs size_index = array_size - 1; 17053dec9fcdSqs } 17063dec9fcdSqs 17073dec9fcdSqs while ((allocated < total_alloc_size) && 17083dec9fcdSqs (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 17093dec9fcdSqs rx_dmap[i].dma_chunk_index = i; 17103dec9fcdSqs rx_dmap[i].block_size = block_size; 17113dec9fcdSqs rx_dmap[i].alength = alloc_sizes[size_index]; 17123dec9fcdSqs rx_dmap[i].orig_alength = rx_dmap[i].alength; 17133dec9fcdSqs rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 17143dec9fcdSqs rx_dmap[i].dma_channel = dma_channel; 17153dec9fcdSqs rx_dmap[i].contig_alloc_type = B_FALSE; 17163dec9fcdSqs 17173dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17183dec9fcdSqs "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 17193dec9fcdSqs "i %d nblocks %d alength %d", 17203dec9fcdSqs dma_channel, i, &rx_dmap[i], block_size, 17213dec9fcdSqs i, rx_dmap[i].nblocks, rx_dmap[i].alength)); 17223dec9fcdSqs status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 17233dec9fcdSqs &hxge_rx_dma_attr, rx_dmap[i].alength, 17243dec9fcdSqs &hxge_dev_buf_dma_acc_attr, 17253dec9fcdSqs DDI_DMA_READ | DDI_DMA_STREAMING, 17263dec9fcdSqs (p_hxge_dma_common_t)(&rx_dmap[i])); 17273dec9fcdSqs if (status != HXGE_OK) { 17283dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 17293dec9fcdSqs " hxge_alloc_rx_buf_dma: Alloc Failed: " 17303dec9fcdSqs " for size: %d", alloc_sizes[size_index])); 17313dec9fcdSqs size_index--; 17323dec9fcdSqs } else { 17333dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 17343dec9fcdSqs " alloc_rx_buf_dma allocated rdc %d " 17353dec9fcdSqs "chunk %d size %x dvma %x bufp %llx ", 17363dec9fcdSqs dma_channel, i, rx_dmap[i].alength, 17373dec9fcdSqs rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 17383dec9fcdSqs i++; 17393dec9fcdSqs allocated += alloc_sizes[size_index]; 17403dec9fcdSqs } 17413dec9fcdSqs } 17423dec9fcdSqs 17433dec9fcdSqs if (allocated < total_alloc_size) { 17443dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 17453dec9fcdSqs " hxge_alloc_rx_buf_dma failed due to" 17463dec9fcdSqs " allocated(%d) < required(%d)", 17473dec9fcdSqs allocated, total_alloc_size)); 17483dec9fcdSqs goto hxge_alloc_rx_mem_fail1; 17493dec9fcdSqs } 17503dec9fcdSqs 17513dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 17523dec9fcdSqs " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i)); 17533dec9fcdSqs 17543dec9fcdSqs *num_chunks = i; 17553dec9fcdSqs *dmap = rx_dmap; 17563dec9fcdSqs 17573dec9fcdSqs goto hxge_alloc_rx_mem_exit; 17583dec9fcdSqs 17593dec9fcdSqs hxge_alloc_rx_mem_fail1: 17603dec9fcdSqs KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 17613dec9fcdSqs 17623dec9fcdSqs hxge_alloc_rx_mem_exit: 17633dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 17643dec9fcdSqs "<== hxge_alloc_rx_buf_dma status 0x%08x", status)); 17653dec9fcdSqs 17663dec9fcdSqs return (status); 17673dec9fcdSqs } 17683dec9fcdSqs 17693dec9fcdSqs /*ARGSUSED*/ 17703dec9fcdSqs static void 17713dec9fcdSqs hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 17723dec9fcdSqs uint32_t num_chunks) 17733dec9fcdSqs { 17743dec9fcdSqs int i; 17753dec9fcdSqs 17763dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17773dec9fcdSqs "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 17783dec9fcdSqs 17793dec9fcdSqs for (i = 0; i < num_chunks; i++) { 17803dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 17813dec9fcdSqs "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap)); 17823dec9fcdSqs hxge_dma_mem_free(dmap++); 17833dec9fcdSqs } 17843dec9fcdSqs 17853dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma")); 17863dec9fcdSqs } 17873dec9fcdSqs 17883dec9fcdSqs /*ARGSUSED*/ 17893dec9fcdSqs static hxge_status_t 17903dec9fcdSqs hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 17913dec9fcdSqs p_hxge_dma_common_t *dmap, size_t size) 17923dec9fcdSqs { 17933dec9fcdSqs p_hxge_dma_common_t rx_dmap; 17943dec9fcdSqs hxge_status_t status = HXGE_OK; 17953dec9fcdSqs 17963dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma")); 17973dec9fcdSqs 17983dec9fcdSqs rx_dmap = (p_hxge_dma_common_t) 17993dec9fcdSqs KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP); 18003dec9fcdSqs 18013dec9fcdSqs rx_dmap->contig_alloc_type = B_FALSE; 18023dec9fcdSqs 18033dec9fcdSqs status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 18043dec9fcdSqs &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr, 18053dec9fcdSqs DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap); 18063dec9fcdSqs if (status != HXGE_OK) { 18073dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 18083dec9fcdSqs " hxge_alloc_rx_cntl_dma: Alloc Failed: " 18093dec9fcdSqs " for size: %d", size)); 18103dec9fcdSqs goto hxge_alloc_rx_cntl_dma_fail1; 18113dec9fcdSqs } 18123dec9fcdSqs 18133dec9fcdSqs *dmap = rx_dmap; 18143dec9fcdSqs 18153dec9fcdSqs goto hxge_alloc_rx_cntl_dma_exit; 18163dec9fcdSqs 18173dec9fcdSqs hxge_alloc_rx_cntl_dma_fail1: 18183dec9fcdSqs KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t)); 18193dec9fcdSqs 18203dec9fcdSqs hxge_alloc_rx_cntl_dma_exit: 18213dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 18223dec9fcdSqs "<== hxge_alloc_rx_cntl_dma status 0x%08x", status)); 18233dec9fcdSqs 18243dec9fcdSqs return (status); 18253dec9fcdSqs } 18263dec9fcdSqs 18273dec9fcdSqs /*ARGSUSED*/ 18283dec9fcdSqs static void 18293dec9fcdSqs hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 18303dec9fcdSqs { 18313dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma")); 18323dec9fcdSqs 18333dec9fcdSqs hxge_dma_mem_free(dmap); 18343dec9fcdSqs 18353dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma")); 18363dec9fcdSqs } 18373dec9fcdSqs 18383dec9fcdSqs static hxge_status_t 18393dec9fcdSqs hxge_alloc_tx_mem_pool(p_hxge_t hxgep) 18403dec9fcdSqs { 18413dec9fcdSqs hxge_status_t status = HXGE_OK; 18423dec9fcdSqs int i, j; 18433dec9fcdSqs uint32_t ndmas, st_tdc; 18443dec9fcdSqs p_hxge_dma_pt_cfg_t p_all_cfgp; 18453dec9fcdSqs p_hxge_hw_pt_cfg_t p_cfgp; 18463dec9fcdSqs p_hxge_dma_pool_t dma_poolp; 18473dec9fcdSqs p_hxge_dma_common_t *dma_buf_p; 18483dec9fcdSqs p_hxge_dma_pool_t dma_cntl_poolp; 18493dec9fcdSqs p_hxge_dma_common_t *dma_cntl_p; 18503dec9fcdSqs size_t tx_buf_alloc_size; 18513dec9fcdSqs size_t tx_cntl_alloc_size; 18523dec9fcdSqs uint32_t *num_chunks; /* per dma */ 18533dec9fcdSqs 18543dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool")); 18553dec9fcdSqs 18563dec9fcdSqs p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 18573dec9fcdSqs p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 18583dec9fcdSqs st_tdc = p_cfgp->start_tdc; 18593dec9fcdSqs ndmas = p_cfgp->max_tdcs; 18603dec9fcdSqs 18613dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: " 18623dec9fcdSqs "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d", 18633dec9fcdSqs p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs)); 18643dec9fcdSqs /* 18653dec9fcdSqs * Allocate memory for each transmit DMA channel. 18663dec9fcdSqs */ 18673dec9fcdSqs dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 18683dec9fcdSqs KM_SLEEP); 18693dec9fcdSqs dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 18703dec9fcdSqs sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 18713dec9fcdSqs 18723dec9fcdSqs dma_cntl_poolp = (p_hxge_dma_pool_t) 18733dec9fcdSqs KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 18743dec9fcdSqs dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 18753dec9fcdSqs sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 18763dec9fcdSqs 18773dec9fcdSqs hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size; 18783dec9fcdSqs 18793dec9fcdSqs /* 18803dec9fcdSqs * Assume that each DMA channel will be configured with default 18813dec9fcdSqs * transmit bufer size for copying transmit data. (For packet payload 18823dec9fcdSqs * over this limit, packets will not be copied.) 18833dec9fcdSqs */ 18843dec9fcdSqs tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size); 18853dec9fcdSqs 18863dec9fcdSqs /* 18873dec9fcdSqs * Addresses of transmit descriptor ring and the mailbox must be all 18883dec9fcdSqs * cache-aligned (64 bytes). 18893dec9fcdSqs */ 18903dec9fcdSqs tx_cntl_alloc_size = hxge_tx_ring_size; 18913dec9fcdSqs tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 18923dec9fcdSqs tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 18933dec9fcdSqs 18943dec9fcdSqs num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 18953dec9fcdSqs KM_SLEEP); 18963dec9fcdSqs 18973dec9fcdSqs /* 18983dec9fcdSqs * Allocate memory for transmit buffers and descriptor rings. Replace 18993dec9fcdSqs * allocation functions with interface functions provided by the 19003dec9fcdSqs * partition manager when it is available. 19013dec9fcdSqs * 19023dec9fcdSqs * Allocate memory for the transmit buffer pool. 19033dec9fcdSqs */ 19043dec9fcdSqs for (i = 0; i < ndmas; i++) { 19053dec9fcdSqs num_chunks[i] = 0; 19063dec9fcdSqs status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i], 19073dec9fcdSqs tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]); 19083dec9fcdSqs if (status != HXGE_OK) { 19093dec9fcdSqs break; 19103dec9fcdSqs } 19113dec9fcdSqs st_tdc++; 19123dec9fcdSqs } 19133dec9fcdSqs 19143dec9fcdSqs if (i < ndmas) { 19153dec9fcdSqs goto hxge_alloc_tx_mem_pool_fail1; 19163dec9fcdSqs } 19173dec9fcdSqs 19183dec9fcdSqs st_tdc = p_cfgp->start_tdc; 19193dec9fcdSqs 19203dec9fcdSqs /* 19213dec9fcdSqs * Allocate memory for descriptor rings and mailbox. 19223dec9fcdSqs */ 19233dec9fcdSqs for (j = 0; j < ndmas; j++) { 19243dec9fcdSqs status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j], 19253dec9fcdSqs tx_cntl_alloc_size); 19263dec9fcdSqs if (status != HXGE_OK) { 19273dec9fcdSqs break; 19283dec9fcdSqs } 19293dec9fcdSqs st_tdc++; 19303dec9fcdSqs } 19313dec9fcdSqs 19323dec9fcdSqs if (j < ndmas) { 19333dec9fcdSqs goto hxge_alloc_tx_mem_pool_fail2; 19343dec9fcdSqs } 19353dec9fcdSqs 19363dec9fcdSqs dma_poolp->ndmas = ndmas; 19373dec9fcdSqs dma_poolp->num_chunks = num_chunks; 19383dec9fcdSqs dma_poolp->buf_allocated = B_TRUE; 19393dec9fcdSqs dma_poolp->dma_buf_pool_p = dma_buf_p; 19403dec9fcdSqs hxgep->tx_buf_pool_p = dma_poolp; 19413dec9fcdSqs 19423dec9fcdSqs dma_cntl_poolp->ndmas = ndmas; 19433dec9fcdSqs dma_cntl_poolp->buf_allocated = B_TRUE; 19443dec9fcdSqs dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 19453dec9fcdSqs hxgep->tx_cntl_pool_p = dma_cntl_poolp; 19463dec9fcdSqs 19473dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, 19483dec9fcdSqs "==> hxge_alloc_tx_mem_pool: start_tdc %d " 19493dec9fcdSqs "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas)); 19503dec9fcdSqs 19513dec9fcdSqs goto hxge_alloc_tx_mem_pool_exit; 19523dec9fcdSqs 19533dec9fcdSqs hxge_alloc_tx_mem_pool_fail2: 19543dec9fcdSqs /* Free control buffers */ 19553dec9fcdSqs j--; 19563dec9fcdSqs for (; j >= 0; j--) { 19573dec9fcdSqs hxge_free_tx_cntl_dma(hxgep, 19583dec9fcdSqs (p_hxge_dma_common_t)dma_cntl_p[j]); 19593dec9fcdSqs } 19603dec9fcdSqs 19613dec9fcdSqs hxge_alloc_tx_mem_pool_fail1: 19623dec9fcdSqs /* Free data buffers */ 19633dec9fcdSqs i--; 19643dec9fcdSqs for (; i >= 0; i--) { 19653dec9fcdSqs hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 19663dec9fcdSqs num_chunks[i]); 19673dec9fcdSqs } 19683dec9fcdSqs 19693dec9fcdSqs KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 19703dec9fcdSqs KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 19713dec9fcdSqs KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 19723dec9fcdSqs KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 19733dec9fcdSqs KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 19743dec9fcdSqs 19753dec9fcdSqs hxge_alloc_tx_mem_pool_exit: 19763dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, 19773dec9fcdSqs "<== hxge_alloc_tx_mem_pool:status 0x%08x", status)); 19783dec9fcdSqs 19793dec9fcdSqs return (status); 19803dec9fcdSqs } 19813dec9fcdSqs 19823dec9fcdSqs static hxge_status_t 19833dec9fcdSqs hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 19843dec9fcdSqs p_hxge_dma_common_t *dmap, size_t alloc_size, 19853dec9fcdSqs size_t block_size, uint32_t *num_chunks) 19863dec9fcdSqs { 19873dec9fcdSqs p_hxge_dma_common_t tx_dmap; 19883dec9fcdSqs hxge_status_t status = HXGE_OK; 19893dec9fcdSqs size_t total_alloc_size; 19903dec9fcdSqs size_t allocated = 0; 19913dec9fcdSqs int i, size_index, array_size; 19923dec9fcdSqs 19933dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma")); 19943dec9fcdSqs 19953dec9fcdSqs tx_dmap = (p_hxge_dma_common_t) 19963dec9fcdSqs KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 19973dec9fcdSqs 19983dec9fcdSqs total_alloc_size = alloc_size; 19993dec9fcdSqs i = 0; 20003dec9fcdSqs size_index = 0; 20013dec9fcdSqs array_size = sizeof (alloc_sizes) / sizeof (size_t); 20023dec9fcdSqs while ((alloc_sizes[size_index] < alloc_size) && 20033dec9fcdSqs (size_index < array_size)) 20043dec9fcdSqs size_index++; 20053dec9fcdSqs if (size_index >= array_size) { 20063dec9fcdSqs size_index = array_size - 1; 20073dec9fcdSqs } 20083dec9fcdSqs 20093dec9fcdSqs while ((allocated < total_alloc_size) && 20103dec9fcdSqs (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 20113dec9fcdSqs tx_dmap[i].dma_chunk_index = i; 20123dec9fcdSqs tx_dmap[i].block_size = block_size; 20133dec9fcdSqs tx_dmap[i].alength = alloc_sizes[size_index]; 20143dec9fcdSqs tx_dmap[i].orig_alength = tx_dmap[i].alength; 20153dec9fcdSqs tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 20163dec9fcdSqs tx_dmap[i].dma_channel = dma_channel; 20173dec9fcdSqs tx_dmap[i].contig_alloc_type = B_FALSE; 20183dec9fcdSqs 20193dec9fcdSqs status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 20203dec9fcdSqs &hxge_tx_dma_attr, tx_dmap[i].alength, 20213dec9fcdSqs &hxge_dev_buf_dma_acc_attr, 20223dec9fcdSqs DDI_DMA_WRITE | DDI_DMA_STREAMING, 20233dec9fcdSqs (p_hxge_dma_common_t)(&tx_dmap[i])); 20243dec9fcdSqs if (status != HXGE_OK) { 20253dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 20263dec9fcdSqs " hxge_alloc_tx_buf_dma: Alloc Failed: " 20273dec9fcdSqs " for size: %d", alloc_sizes[size_index])); 20283dec9fcdSqs size_index--; 20293dec9fcdSqs } else { 20303dec9fcdSqs i++; 20313dec9fcdSqs allocated += alloc_sizes[size_index]; 20323dec9fcdSqs } 20333dec9fcdSqs } 20343dec9fcdSqs 20353dec9fcdSqs if (allocated < total_alloc_size) { 20363dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 20373dec9fcdSqs " hxge_alloc_tx_buf_dma: failed due to" 20383dec9fcdSqs " allocated(%d) < required(%d)", 20393dec9fcdSqs allocated, total_alloc_size)); 20403dec9fcdSqs goto hxge_alloc_tx_mem_fail1; 20413dec9fcdSqs } 20423dec9fcdSqs 20433dec9fcdSqs *num_chunks = i; 20443dec9fcdSqs *dmap = tx_dmap; 20453dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 20463dec9fcdSqs "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 20473dec9fcdSqs *dmap, i)); 20483dec9fcdSqs goto hxge_alloc_tx_mem_exit; 20493dec9fcdSqs 20503dec9fcdSqs hxge_alloc_tx_mem_fail1: 20513dec9fcdSqs KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 20523dec9fcdSqs 20533dec9fcdSqs hxge_alloc_tx_mem_exit: 20543dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 20553dec9fcdSqs "<== hxge_alloc_tx_buf_dma status 0x%08x", status)); 20563dec9fcdSqs 20573dec9fcdSqs return (status); 20583dec9fcdSqs } 20593dec9fcdSqs 20603dec9fcdSqs /*ARGSUSED*/ 20613dec9fcdSqs static void 20623dec9fcdSqs hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 20633dec9fcdSqs uint32_t num_chunks) 20643dec9fcdSqs { 20653dec9fcdSqs int i; 20663dec9fcdSqs 20673dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma")); 20683dec9fcdSqs 20693dec9fcdSqs for (i = 0; i < num_chunks; i++) { 20703dec9fcdSqs hxge_dma_mem_free(dmap++); 20713dec9fcdSqs } 20723dec9fcdSqs 20733dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma")); 20743dec9fcdSqs } 20753dec9fcdSqs 20763dec9fcdSqs /*ARGSUSED*/ 20773dec9fcdSqs static hxge_status_t 20783dec9fcdSqs hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 20793dec9fcdSqs p_hxge_dma_common_t *dmap, size_t size) 20803dec9fcdSqs { 20813dec9fcdSqs p_hxge_dma_common_t tx_dmap; 20823dec9fcdSqs hxge_status_t status = HXGE_OK; 20833dec9fcdSqs 20843dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma")); 20853dec9fcdSqs 20863dec9fcdSqs tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t), 20873dec9fcdSqs KM_SLEEP); 20883dec9fcdSqs 20893dec9fcdSqs tx_dmap->contig_alloc_type = B_FALSE; 20903dec9fcdSqs 20913dec9fcdSqs status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 20923dec9fcdSqs &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr, 20933dec9fcdSqs DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap); 20943dec9fcdSqs if (status != HXGE_OK) { 20953dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 20963dec9fcdSqs " hxge_alloc_tx_cntl_dma: Alloc Failed: " 20973dec9fcdSqs " for size: %d", size)); 20983dec9fcdSqs goto hxge_alloc_tx_cntl_dma_fail1; 20993dec9fcdSqs } 21003dec9fcdSqs 21013dec9fcdSqs *dmap = tx_dmap; 21023dec9fcdSqs 21033dec9fcdSqs goto hxge_alloc_tx_cntl_dma_exit; 21043dec9fcdSqs 21053dec9fcdSqs hxge_alloc_tx_cntl_dma_fail1: 21063dec9fcdSqs KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t)); 21073dec9fcdSqs 21083dec9fcdSqs hxge_alloc_tx_cntl_dma_exit: 21093dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 21103dec9fcdSqs "<== hxge_alloc_tx_cntl_dma status 0x%08x", status)); 21113dec9fcdSqs 21123dec9fcdSqs return (status); 21133dec9fcdSqs } 21143dec9fcdSqs 21153dec9fcdSqs /*ARGSUSED*/ 21163dec9fcdSqs static void 21173dec9fcdSqs hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 21183dec9fcdSqs { 21193dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma")); 21203dec9fcdSqs 21213dec9fcdSqs hxge_dma_mem_free(dmap); 21223dec9fcdSqs 21233dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma")); 21243dec9fcdSqs } 21253dec9fcdSqs 21263dec9fcdSqs static void 21273dec9fcdSqs hxge_free_tx_mem_pool(p_hxge_t hxgep) 21283dec9fcdSqs { 21293dec9fcdSqs uint32_t i, ndmas; 21303dec9fcdSqs p_hxge_dma_pool_t dma_poolp; 21313dec9fcdSqs p_hxge_dma_common_t *dma_buf_p; 21323dec9fcdSqs p_hxge_dma_pool_t dma_cntl_poolp; 21333dec9fcdSqs p_hxge_dma_common_t *dma_cntl_p; 21343dec9fcdSqs uint32_t *num_chunks; 21353dec9fcdSqs 21363dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool")); 21373dec9fcdSqs 21383dec9fcdSqs dma_poolp = hxgep->tx_buf_pool_p; 21393dec9fcdSqs if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 21403dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 21413dec9fcdSqs "<== hxge_free_tx_mem_pool " 21423dec9fcdSqs "(null rx buf pool or buf not allocated")); 21433dec9fcdSqs return; 21443dec9fcdSqs } 21453dec9fcdSqs 21463dec9fcdSqs dma_cntl_poolp = hxgep->tx_cntl_pool_p; 21473dec9fcdSqs if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 21483dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 21493dec9fcdSqs "<== hxge_free_tx_mem_pool " 21503dec9fcdSqs "(null tx cntl buf pool or cntl buf not allocated")); 21513dec9fcdSqs return; 21523dec9fcdSqs } 21533dec9fcdSqs 21543dec9fcdSqs dma_buf_p = dma_poolp->dma_buf_pool_p; 21553dec9fcdSqs num_chunks = dma_poolp->num_chunks; 21563dec9fcdSqs 21573dec9fcdSqs dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 21583dec9fcdSqs ndmas = dma_cntl_poolp->ndmas; 21593dec9fcdSqs 21603dec9fcdSqs for (i = 0; i < ndmas; i++) { 21613dec9fcdSqs hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 21623dec9fcdSqs } 21633dec9fcdSqs 21643dec9fcdSqs for (i = 0; i < ndmas; i++) { 21653dec9fcdSqs hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]); 21663dec9fcdSqs } 21673dec9fcdSqs 21683dec9fcdSqs for (i = 0; i < ndmas; i++) { 21693dec9fcdSqs KMEM_FREE(dma_buf_p[i], 21703dec9fcdSqs sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 21713dec9fcdSqs KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t)); 21723dec9fcdSqs } 21733dec9fcdSqs 21743dec9fcdSqs KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 21753dec9fcdSqs KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 21763dec9fcdSqs KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 21773dec9fcdSqs KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 21783dec9fcdSqs KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 21793dec9fcdSqs 21803dec9fcdSqs hxgep->tx_buf_pool_p = NULL; 21813dec9fcdSqs hxgep->tx_cntl_pool_p = NULL; 21823dec9fcdSqs 21833dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool")); 21843dec9fcdSqs } 21853dec9fcdSqs 21863dec9fcdSqs /*ARGSUSED*/ 21873dec9fcdSqs static hxge_status_t 21883dec9fcdSqs hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method, 21893dec9fcdSqs struct ddi_dma_attr *dma_attrp, 21903dec9fcdSqs size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 21913dec9fcdSqs p_hxge_dma_common_t dma_p) 21923dec9fcdSqs { 21933dec9fcdSqs caddr_t kaddrp; 21943dec9fcdSqs int ddi_status = DDI_SUCCESS; 21953dec9fcdSqs 21963dec9fcdSqs dma_p->dma_handle = NULL; 21973dec9fcdSqs dma_p->acc_handle = NULL; 21983dec9fcdSqs dma_p->kaddrp = NULL; 21993dec9fcdSqs 22003dec9fcdSqs ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp, 22013dec9fcdSqs DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 22023dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 22033dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22043dec9fcdSqs "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 22053dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 22063dec9fcdSqs } 22073dec9fcdSqs 22083dec9fcdSqs ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p, 22093dec9fcdSqs xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 22103dec9fcdSqs &dma_p->acc_handle); 22113dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 22123dec9fcdSqs /* The caller will decide whether it is fatal */ 22133dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 22143dec9fcdSqs "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 22153dec9fcdSqs ddi_dma_free_handle(&dma_p->dma_handle); 22163dec9fcdSqs dma_p->dma_handle = NULL; 22173dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 22183dec9fcdSqs } 22193dec9fcdSqs 22203dec9fcdSqs if (dma_p->alength < length) { 22213dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22223dec9fcdSqs "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length.")); 22233dec9fcdSqs ddi_dma_mem_free(&dma_p->acc_handle); 22243dec9fcdSqs ddi_dma_free_handle(&dma_p->dma_handle); 22253dec9fcdSqs dma_p->acc_handle = NULL; 22263dec9fcdSqs dma_p->dma_handle = NULL; 22273dec9fcdSqs return (HXGE_ERROR); 22283dec9fcdSqs } 22293dec9fcdSqs 22303dec9fcdSqs ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 22313dec9fcdSqs kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 22323dec9fcdSqs &dma_p->dma_cookie, &dma_p->ncookies); 22333dec9fcdSqs if (ddi_status != DDI_DMA_MAPPED) { 22343dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22353dec9fcdSqs "hxge_dma_mem_alloc:di_dma_addr_bind failed " 22363dec9fcdSqs "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 22373dec9fcdSqs if (dma_p->acc_handle) { 22383dec9fcdSqs ddi_dma_mem_free(&dma_p->acc_handle); 22393dec9fcdSqs dma_p->acc_handle = NULL; 22403dec9fcdSqs } 22413dec9fcdSqs ddi_dma_free_handle(&dma_p->dma_handle); 22423dec9fcdSqs dma_p->dma_handle = NULL; 22433dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 22443dec9fcdSqs } 22453dec9fcdSqs 22463dec9fcdSqs if (dma_p->ncookies != 1) { 22473dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, 22483dec9fcdSqs "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie" 22493dec9fcdSqs "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 22503dec9fcdSqs if (dma_p->acc_handle) { 22513dec9fcdSqs ddi_dma_mem_free(&dma_p->acc_handle); 22523dec9fcdSqs dma_p->acc_handle = NULL; 22533dec9fcdSqs } 22543dec9fcdSqs (void) ddi_dma_unbind_handle(dma_p->dma_handle); 22553dec9fcdSqs ddi_dma_free_handle(&dma_p->dma_handle); 22563dec9fcdSqs dma_p->dma_handle = NULL; 22573dec9fcdSqs return (HXGE_ERROR); 22583dec9fcdSqs } 22593dec9fcdSqs 22603dec9fcdSqs dma_p->kaddrp = kaddrp; 22613dec9fcdSqs #if defined(__i386) 22623dec9fcdSqs dma_p->ioaddr_pp = 22633dec9fcdSqs (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 22643dec9fcdSqs #else 22653dec9fcdSqs dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress; 22663dec9fcdSqs #endif 22673dec9fcdSqs 22683dec9fcdSqs HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 22693dec9fcdSqs 22703dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: " 22713dec9fcdSqs "dma buffer allocated: dma_p $%p " 22723dec9fcdSqs "return dmac_ladress from cookie $%p dmac_size %d " 22733dec9fcdSqs "dma_p->ioaddr_p $%p " 22743dec9fcdSqs "dma_p->orig_ioaddr_p $%p " 22753dec9fcdSqs "orig_vatopa $%p " 22763dec9fcdSqs "alength %d (0x%x) " 22773dec9fcdSqs "kaddrp $%p " 22783dec9fcdSqs "length %d (0x%x)", 22793dec9fcdSqs dma_p, 22803dec9fcdSqs dma_p->dma_cookie.dmac_laddress, 22813dec9fcdSqs dma_p->dma_cookie.dmac_size, 22823dec9fcdSqs dma_p->ioaddr_pp, 22833dec9fcdSqs dma_p->orig_ioaddr_pp, 22843dec9fcdSqs dma_p->orig_vatopa, 22853dec9fcdSqs dma_p->alength, dma_p->alength, 22863dec9fcdSqs kaddrp, 22873dec9fcdSqs length, length)); 22883dec9fcdSqs 22893dec9fcdSqs return (HXGE_OK); 22903dec9fcdSqs } 22913dec9fcdSqs 22923dec9fcdSqs static void 22933dec9fcdSqs hxge_dma_mem_free(p_hxge_dma_common_t dma_p) 22943dec9fcdSqs { 22953dec9fcdSqs if (dma_p->dma_handle != NULL) { 22963dec9fcdSqs if (dma_p->ncookies) { 22973dec9fcdSqs (void) ddi_dma_unbind_handle(dma_p->dma_handle); 22983dec9fcdSqs dma_p->ncookies = 0; 22993dec9fcdSqs } 23003dec9fcdSqs ddi_dma_free_handle(&dma_p->dma_handle); 23013dec9fcdSqs dma_p->dma_handle = NULL; 23023dec9fcdSqs } 23033dec9fcdSqs if (dma_p->acc_handle != NULL) { 23043dec9fcdSqs ddi_dma_mem_free(&dma_p->acc_handle); 23053dec9fcdSqs dma_p->acc_handle = NULL; 23063dec9fcdSqs HPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 23073dec9fcdSqs } 23083dec9fcdSqs dma_p->kaddrp = NULL; 23093dec9fcdSqs dma_p->alength = NULL; 23103dec9fcdSqs } 23113dec9fcdSqs 23123dec9fcdSqs /* 23133dec9fcdSqs * hxge_m_start() -- start transmitting and receiving. 23143dec9fcdSqs * 23153dec9fcdSqs * This function is called by the MAC layer when the first 23163dec9fcdSqs * stream is open to prepare the hardware ready for sending 23173dec9fcdSqs * and transmitting packets. 23183dec9fcdSqs */ 23193dec9fcdSqs static int 23203dec9fcdSqs hxge_m_start(void *arg) 23213dec9fcdSqs { 23223dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 23233dec9fcdSqs 23243dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start")); 23253dec9fcdSqs 23263dec9fcdSqs MUTEX_ENTER(hxgep->genlock); 23273dec9fcdSqs 23283dec9fcdSqs if (hxge_init(hxgep) != DDI_SUCCESS) { 23293dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23303dec9fcdSqs "<== hxge_m_start: initialization failed")); 23313dec9fcdSqs MUTEX_EXIT(hxgep->genlock); 23323dec9fcdSqs return (EIO); 23333dec9fcdSqs } 23343dec9fcdSqs 23353dec9fcdSqs if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) { 23363dec9fcdSqs /* 23373dec9fcdSqs * Start timer to check the system error and tx hangs 23383dec9fcdSqs */ 23393dec9fcdSqs hxgep->hxge_timerid = hxge_start_timer(hxgep, 23403dec9fcdSqs hxge_check_hw_state, HXGE_CHECK_TIMER); 23413dec9fcdSqs 23423dec9fcdSqs hxgep->hxge_mac_state = HXGE_MAC_STARTED; 23433dec9fcdSqs } 23443dec9fcdSqs 23453dec9fcdSqs MUTEX_EXIT(hxgep->genlock); 23463dec9fcdSqs 23473dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start")); 23483dec9fcdSqs 23493dec9fcdSqs return (0); 23503dec9fcdSqs } 23513dec9fcdSqs 23523dec9fcdSqs /* 23533dec9fcdSqs * hxge_m_stop(): stop transmitting and receiving. 23543dec9fcdSqs */ 23553dec9fcdSqs static void 23563dec9fcdSqs hxge_m_stop(void *arg) 23573dec9fcdSqs { 23583dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 23593dec9fcdSqs 23603dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop")); 23613dec9fcdSqs 23623dec9fcdSqs if (hxgep->hxge_timerid) { 23633dec9fcdSqs hxge_stop_timer(hxgep, hxgep->hxge_timerid); 23643dec9fcdSqs hxgep->hxge_timerid = 0; 23653dec9fcdSqs } 23663dec9fcdSqs 23673dec9fcdSqs MUTEX_ENTER(hxgep->genlock); 23683dec9fcdSqs 23693dec9fcdSqs hxge_uninit(hxgep); 23703dec9fcdSqs 23713dec9fcdSqs hxgep->hxge_mac_state = HXGE_MAC_STOPPED; 23723dec9fcdSqs 23733dec9fcdSqs MUTEX_EXIT(hxgep->genlock); 23743dec9fcdSqs 23753dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop")); 23763dec9fcdSqs } 23773dec9fcdSqs 23783dec9fcdSqs static int 23793dec9fcdSqs hxge_m_unicst(void *arg, const uint8_t *macaddr) 23803dec9fcdSqs { 23813dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 23823dec9fcdSqs struct ether_addr addrp; 23833dec9fcdSqs hxge_status_t status; 23843dec9fcdSqs 23853dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_unicst")); 23863dec9fcdSqs 23873dec9fcdSqs bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 23883dec9fcdSqs 23893dec9fcdSqs status = hxge_set_mac_addr(hxgep, &addrp); 23903dec9fcdSqs if (status != HXGE_OK) { 23913dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23923dec9fcdSqs "<== hxge_m_unicst: set unitcast failed")); 23933dec9fcdSqs return (EINVAL); 23943dec9fcdSqs } 23953dec9fcdSqs 23963dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_unicst")); 23973dec9fcdSqs 23983dec9fcdSqs return (0); 23993dec9fcdSqs } 24003dec9fcdSqs 24013dec9fcdSqs static int 24023dec9fcdSqs hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 24033dec9fcdSqs { 24043dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 24053dec9fcdSqs struct ether_addr addrp; 24063dec9fcdSqs 24073dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add)); 24083dec9fcdSqs 24093dec9fcdSqs bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 24103dec9fcdSqs 24113dec9fcdSqs if (add) { 24123dec9fcdSqs if (hxge_add_mcast_addr(hxgep, &addrp)) { 24133dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24143dec9fcdSqs "<== hxge_m_multicst: add multicast failed")); 24153dec9fcdSqs return (EINVAL); 24163dec9fcdSqs } 24173dec9fcdSqs } else { 24183dec9fcdSqs if (hxge_del_mcast_addr(hxgep, &addrp)) { 24193dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24203dec9fcdSqs "<== hxge_m_multicst: del multicast failed")); 24213dec9fcdSqs return (EINVAL); 24223dec9fcdSqs } 24233dec9fcdSqs } 24243dec9fcdSqs 24253dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst")); 24263dec9fcdSqs 24273dec9fcdSqs return (0); 24283dec9fcdSqs } 24293dec9fcdSqs 24303dec9fcdSqs static int 24313dec9fcdSqs hxge_m_promisc(void *arg, boolean_t on) 24323dec9fcdSqs { 24333dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 24343dec9fcdSqs 24353dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on)); 24363dec9fcdSqs 24373dec9fcdSqs if (hxge_set_promisc(hxgep, on)) { 24383dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24393dec9fcdSqs "<== hxge_m_promisc: set promisc failed")); 24403dec9fcdSqs return (EINVAL); 24413dec9fcdSqs } 24423dec9fcdSqs 24433dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on)); 24443dec9fcdSqs 24453dec9fcdSqs return (0); 24463dec9fcdSqs } 24473dec9fcdSqs 24483dec9fcdSqs static void 24493dec9fcdSqs hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 24503dec9fcdSqs { 24513dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 24523dec9fcdSqs struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 24533dec9fcdSqs boolean_t need_privilege; 24543dec9fcdSqs int err; 24553dec9fcdSqs int cmd; 24563dec9fcdSqs 24573dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl")); 24583dec9fcdSqs 24593dec9fcdSqs iocp = (struct iocblk *)mp->b_rptr; 24603dec9fcdSqs iocp->ioc_error = 0; 24613dec9fcdSqs need_privilege = B_TRUE; 24623dec9fcdSqs cmd = iocp->ioc_cmd; 24633dec9fcdSqs 24643dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd)); 24653dec9fcdSqs switch (cmd) { 24663dec9fcdSqs default: 24673dec9fcdSqs miocnak(wq, mp, 0, EINVAL); 24683dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid")); 24693dec9fcdSqs return; 24703dec9fcdSqs 24713dec9fcdSqs case LB_GET_INFO_SIZE: 24723dec9fcdSqs case LB_GET_INFO: 24733dec9fcdSqs case LB_GET_MODE: 24743dec9fcdSqs need_privilege = B_FALSE; 24753dec9fcdSqs break; 24763dec9fcdSqs 24773dec9fcdSqs case LB_SET_MODE: 24783dec9fcdSqs break; 24793dec9fcdSqs 24803dec9fcdSqs case ND_GET: 24813dec9fcdSqs need_privilege = B_FALSE; 24823dec9fcdSqs break; 24833dec9fcdSqs case ND_SET: 24843dec9fcdSqs break; 24853dec9fcdSqs 24863dec9fcdSqs case HXGE_GET64: 24873dec9fcdSqs case HXGE_PUT64: 24883dec9fcdSqs case HXGE_GET_TX_RING_SZ: 24893dec9fcdSqs case HXGE_GET_TX_DESC: 24903dec9fcdSqs case HXGE_TX_SIDE_RESET: 24913dec9fcdSqs case HXGE_RX_SIDE_RESET: 24923dec9fcdSqs case HXGE_GLOBAL_RESET: 24933dec9fcdSqs case HXGE_RESET_MAC: 24943dec9fcdSqs case HXGE_PUT_TCAM: 24953dec9fcdSqs case HXGE_GET_TCAM: 24963dec9fcdSqs case HXGE_RTRACE: 24973dec9fcdSqs 24983dec9fcdSqs need_privilege = B_FALSE; 24993dec9fcdSqs break; 25003dec9fcdSqs } 25013dec9fcdSqs 25023dec9fcdSqs if (need_privilege) { 25033dec9fcdSqs err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 25043dec9fcdSqs if (err != 0) { 25053dec9fcdSqs miocnak(wq, mp, 0, err); 25063dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25073dec9fcdSqs "<== hxge_m_ioctl: no priv")); 25083dec9fcdSqs return; 25093dec9fcdSqs } 25103dec9fcdSqs } 25113dec9fcdSqs 25123dec9fcdSqs switch (cmd) { 25133dec9fcdSqs case ND_GET: 25143dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command")); 25153dec9fcdSqs case ND_SET: 25163dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command")); 25173dec9fcdSqs hxge_param_ioctl(hxgep, wq, mp, iocp); 25183dec9fcdSqs break; 25193dec9fcdSqs 25203dec9fcdSqs case LB_GET_MODE: 25213dec9fcdSqs case LB_SET_MODE: 25223dec9fcdSqs case LB_GET_INFO_SIZE: 25233dec9fcdSqs case LB_GET_INFO: 25243dec9fcdSqs hxge_loopback_ioctl(hxgep, wq, mp, iocp); 25253dec9fcdSqs break; 25263dec9fcdSqs 25273dec9fcdSqs case HXGE_PUT_TCAM: 25283dec9fcdSqs case HXGE_GET_TCAM: 25293dec9fcdSqs case HXGE_GET64: 25303dec9fcdSqs case HXGE_PUT64: 25313dec9fcdSqs case HXGE_GET_TX_RING_SZ: 25323dec9fcdSqs case HXGE_GET_TX_DESC: 25333dec9fcdSqs case HXGE_TX_SIDE_RESET: 25343dec9fcdSqs case HXGE_RX_SIDE_RESET: 25353dec9fcdSqs case HXGE_GLOBAL_RESET: 25363dec9fcdSqs case HXGE_RESET_MAC: 25373dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, 25383dec9fcdSqs "==> hxge_m_ioctl: cmd 0x%x", cmd)); 25393dec9fcdSqs hxge_hw_ioctl(hxgep, wq, mp, iocp); 25403dec9fcdSqs break; 25413dec9fcdSqs } 25423dec9fcdSqs 25433dec9fcdSqs HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl")); 25443dec9fcdSqs } 25453dec9fcdSqs 25463dec9fcdSqs extern void hxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 25473dec9fcdSqs 25483dec9fcdSqs static void 25493dec9fcdSqs hxge_m_resources(void *arg) 25503dec9fcdSqs { 25513dec9fcdSqs p_hxge_t hxgep = arg; 25523dec9fcdSqs mac_rx_fifo_t mrf; 25533dec9fcdSqs p_rx_rcr_rings_t rcr_rings; 25543dec9fcdSqs p_rx_rcr_ring_t *rcr_p; 25553dec9fcdSqs p_rx_rcr_ring_t rcrp; 25563dec9fcdSqs uint32_t i, ndmas; 25573dec9fcdSqs int status; 25583dec9fcdSqs 25593dec9fcdSqs HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources")); 25603dec9fcdSqs 25613dec9fcdSqs MUTEX_ENTER(hxgep->genlock); 25623dec9fcdSqs 25633dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 25643dec9fcdSqs status = hxge_init(hxgep); 25653dec9fcdSqs if (status != HXGE_OK) { 25663dec9fcdSqs HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources: " 25673dec9fcdSqs "hxge_init failed")); 25683dec9fcdSqs MUTEX_EXIT(hxgep->genlock); 25693dec9fcdSqs return; 25703dec9fcdSqs } 25713dec9fcdSqs } 25723dec9fcdSqs 25733dec9fcdSqs mrf.mrf_type = MAC_RX_FIFO; 25743dec9fcdSqs mrf.mrf_blank = hxge_rx_hw_blank; 2575fe930412Sqs mrf.mrf_arg = (void *)hxgep; 25763dec9fcdSqs 2577fe930412Sqs mrf.mrf_normal_blank_time = RXDMA_RCR_TO_DEFAULT; 2578fe930412Sqs mrf.mrf_normal_pkt_count = RXDMA_RCR_PTHRES_DEFAULT; 25793dec9fcdSqs 25803dec9fcdSqs rcr_rings = hxgep->rx_rcr_rings; 25813dec9fcdSqs rcr_p = rcr_rings->rcr_rings; 25823dec9fcdSqs ndmas = rcr_rings->ndmas; 25833dec9fcdSqs 25843dec9fcdSqs /* 25853dec9fcdSqs * Export our receive resources to the MAC layer. 25863dec9fcdSqs */ 25873dec9fcdSqs for (i = 0; i < ndmas; i++) { 25883dec9fcdSqs rcrp = (void *)(p_rx_rcr_ring_t)rcr_p[i]; 25893dec9fcdSqs rcrp->rcr_mac_handle = 25903dec9fcdSqs mac_resource_add(hxgep->mach, (mac_resource_t *)&mrf); 25913dec9fcdSqs 25923dec9fcdSqs HXGE_DEBUG_MSG((hxgep, RX_CTL, 25933dec9fcdSqs "==> hxge_m_resources: vdma %d dma %d " 25943dec9fcdSqs "rcrptr 0x%016llx mac_handle 0x%016llx", 25953dec9fcdSqs i, rcrp->rdc, rcr_p[i], rcrp->rcr_mac_handle)); 25963dec9fcdSqs } 25973dec9fcdSqs 25983dec9fcdSqs MUTEX_EXIT(hxgep->genlock); 25993dec9fcdSqs 26003dec9fcdSqs HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_m_resources")); 26013dec9fcdSqs } 26023dec9fcdSqs 26033dec9fcdSqs /* 26043dec9fcdSqs * Set an alternate MAC address 26053dec9fcdSqs */ 26063dec9fcdSqs static int 26073dec9fcdSqs hxge_altmac_set(p_hxge_t hxgep, uint8_t *maddr, mac_addr_slot_t slot) 26083dec9fcdSqs { 26093dec9fcdSqs uint64_t address; 26103dec9fcdSqs uint64_t tmp; 26113dec9fcdSqs hpi_status_t status; 26123dec9fcdSqs uint8_t addrn; 26133dec9fcdSqs int i; 26143dec9fcdSqs 26153dec9fcdSqs /* 26163dec9fcdSqs * Convert a byte array to a 48 bit value. 26173dec9fcdSqs * Need to check endianess if in doubt 26183dec9fcdSqs */ 26193dec9fcdSqs address = 0; 26203dec9fcdSqs for (i = 0; i < ETHERADDRL; i++) { 26213dec9fcdSqs tmp = maddr[i]; 26223dec9fcdSqs address <<= 8; 26233dec9fcdSqs address |= tmp; 26243dec9fcdSqs } 26253dec9fcdSqs 26263dec9fcdSqs addrn = (uint8_t)slot; 26273dec9fcdSqs status = hpi_pfc_set_mac_address(hxgep->hpi_handle, addrn, address); 26283dec9fcdSqs if (status != HPI_SUCCESS) 26293dec9fcdSqs return (EIO); 26303dec9fcdSqs 26313dec9fcdSqs return (0); 26323dec9fcdSqs } 26333dec9fcdSqs 26343dec9fcdSqs static void 26353dec9fcdSqs hxge_mmac_kstat_update(p_hxge_t hxgep, mac_addr_slot_t slot) 26363dec9fcdSqs { 26373dec9fcdSqs p_hxge_mmac_stats_t mmac_stats; 26383dec9fcdSqs int i; 26393dec9fcdSqs hxge_mmac_t *mmac_info; 26403dec9fcdSqs 26413dec9fcdSqs mmac_info = &hxgep->hxge_mmac_info; 26423dec9fcdSqs mmac_stats = &hxgep->statsp->mmac_stats; 26433dec9fcdSqs mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 26443dec9fcdSqs mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 26453dec9fcdSqs 26463dec9fcdSqs for (i = 0; i < ETHERADDRL; i++) { 26473dec9fcdSqs mmac_stats->mmac_avail_pool[slot].ether_addr_octet[i] = 26483dec9fcdSqs mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i]; 26493dec9fcdSqs } 26503dec9fcdSqs } 26513dec9fcdSqs 26523dec9fcdSqs /* 26533dec9fcdSqs * Find an unused address slot, set the address value to the one specified, 26543dec9fcdSqs * enable the port to start filtering on the new MAC address. 26553dec9fcdSqs * Returns: 0 on success. 26563dec9fcdSqs */ 26573dec9fcdSqs int 26583dec9fcdSqs hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 26593dec9fcdSqs { 26603dec9fcdSqs p_hxge_t hxgep = arg; 26613dec9fcdSqs mac_addr_slot_t slot; 26623dec9fcdSqs hxge_mmac_t *mmac_info; 26633dec9fcdSqs int err; 26643dec9fcdSqs hxge_status_t status; 26653dec9fcdSqs 26663dec9fcdSqs mutex_enter(hxgep->genlock); 26673dec9fcdSqs 26683dec9fcdSqs /* 26693dec9fcdSqs * Make sure that hxge is initialized, if _start() has 26703dec9fcdSqs * not been called. 26713dec9fcdSqs */ 26723dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 26733dec9fcdSqs status = hxge_init(hxgep); 26743dec9fcdSqs if (status != HXGE_OK) { 26753dec9fcdSqs mutex_exit(hxgep->genlock); 26763dec9fcdSqs return (ENXIO); 26773dec9fcdSqs } 26783dec9fcdSqs } 26793dec9fcdSqs 26803dec9fcdSqs mmac_info = &hxgep->hxge_mmac_info; 26813dec9fcdSqs if (mmac_info->naddrfree == 0) { 26823dec9fcdSqs mutex_exit(hxgep->genlock); 26833dec9fcdSqs return (ENOSPC); 26843dec9fcdSqs } 26853dec9fcdSqs 26863dec9fcdSqs if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr, 26873dec9fcdSqs maddr->mma_addrlen)) { 26883dec9fcdSqs mutex_exit(hxgep->genlock); 26893dec9fcdSqs return (EINVAL); 26903dec9fcdSqs } 26913dec9fcdSqs 26923dec9fcdSqs /* 26933dec9fcdSqs * Search for the first available slot. Because naddrfree 26943dec9fcdSqs * is not zero, we are guaranteed to find one. 26953dec9fcdSqs * Slot 0 is for unique (primary) MAC. The first alternate 26963dec9fcdSqs * MAC slot is slot 1. 26973dec9fcdSqs */ 26983dec9fcdSqs for (slot = 1; slot < mmac_info->num_mmac; slot++) { 26993dec9fcdSqs if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 27003dec9fcdSqs break; 27013dec9fcdSqs } 27023dec9fcdSqs 27033dec9fcdSqs ASSERT(slot < mmac_info->num_mmac); 27043dec9fcdSqs if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, slot)) != 0) { 27053dec9fcdSqs mutex_exit(hxgep->genlock); 27063dec9fcdSqs return (err); 27073dec9fcdSqs } 27083dec9fcdSqs bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 27093dec9fcdSqs mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 27103dec9fcdSqs mmac_info->naddrfree--; 27113dec9fcdSqs hxge_mmac_kstat_update(hxgep, slot); 27123dec9fcdSqs 27133dec9fcdSqs maddr->mma_slot = slot; 27143dec9fcdSqs 27153dec9fcdSqs mutex_exit(hxgep->genlock); 27163dec9fcdSqs return (0); 27173dec9fcdSqs } 27183dec9fcdSqs 27193dec9fcdSqs /* 27203dec9fcdSqs * Remove the specified mac address and update 27213dec9fcdSqs * the h/w not to filter the mac address anymore. 27223dec9fcdSqs * Returns: 0, on success. 27233dec9fcdSqs */ 27243dec9fcdSqs int 27253dec9fcdSqs hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 27263dec9fcdSqs { 27273dec9fcdSqs p_hxge_t hxgep = arg; 27283dec9fcdSqs hxge_mmac_t *mmac_info; 27293dec9fcdSqs int err = 0; 27303dec9fcdSqs hxge_status_t status; 27313dec9fcdSqs 27323dec9fcdSqs mutex_enter(hxgep->genlock); 27333dec9fcdSqs 27343dec9fcdSqs /* 27353dec9fcdSqs * Make sure that hxge is initialized, if _start() has 27363dec9fcdSqs * not been called. 27373dec9fcdSqs */ 27383dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 27393dec9fcdSqs status = hxge_init(hxgep); 27403dec9fcdSqs if (status != HXGE_OK) { 27413dec9fcdSqs mutex_exit(hxgep->genlock); 27423dec9fcdSqs return (ENXIO); 27433dec9fcdSqs } 27443dec9fcdSqs } 27453dec9fcdSqs 27463dec9fcdSqs mmac_info = &hxgep->hxge_mmac_info; 27473dec9fcdSqs if (slot <= 0 || slot >= mmac_info->num_mmac) { 27483dec9fcdSqs mutex_exit(hxgep->genlock); 27493dec9fcdSqs return (EINVAL); 27503dec9fcdSqs } 27513dec9fcdSqs 27523dec9fcdSqs if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 27533dec9fcdSqs if (hpi_pfc_mac_addr_disable(hxgep->hpi_handle, slot) == 27543dec9fcdSqs HPI_SUCCESS) { 27553dec9fcdSqs mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 27563dec9fcdSqs mmac_info->naddrfree++; 27573dec9fcdSqs /* 27583dec9fcdSqs * Clear mac_pool[slot].addr so that kstat shows 0 27593dec9fcdSqs * alternate MAC address if the slot is not used. 27603dec9fcdSqs */ 27613dec9fcdSqs bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 27623dec9fcdSqs hxge_mmac_kstat_update(hxgep, slot); 27633dec9fcdSqs } else { 27643dec9fcdSqs err = EIO; 27653dec9fcdSqs } 27663dec9fcdSqs } else { 27673dec9fcdSqs err = EINVAL; 27683dec9fcdSqs } 27693dec9fcdSqs 27703dec9fcdSqs mutex_exit(hxgep->genlock); 27713dec9fcdSqs return (err); 27723dec9fcdSqs } 27733dec9fcdSqs 27743dec9fcdSqs /* 27753dec9fcdSqs * Modify a mac address added by hxge_mmac_add(). 27763dec9fcdSqs * Returns: 0, on success. 27773dec9fcdSqs */ 27783dec9fcdSqs int 27793dec9fcdSqs hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 27803dec9fcdSqs { 27813dec9fcdSqs p_hxge_t hxgep = arg; 27823dec9fcdSqs mac_addr_slot_t slot; 27833dec9fcdSqs hxge_mmac_t *mmac_info; 27843dec9fcdSqs int err = 0; 27853dec9fcdSqs hxge_status_t status; 27863dec9fcdSqs 27873dec9fcdSqs if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr, 27883dec9fcdSqs maddr->mma_addrlen)) 27893dec9fcdSqs return (EINVAL); 27903dec9fcdSqs 27913dec9fcdSqs slot = maddr->mma_slot; 27923dec9fcdSqs 27933dec9fcdSqs mutex_enter(hxgep->genlock); 27943dec9fcdSqs 27953dec9fcdSqs /* 27963dec9fcdSqs * Make sure that hxge is initialized, if _start() has 27973dec9fcdSqs * not been called. 27983dec9fcdSqs */ 27993dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 28003dec9fcdSqs status = hxge_init(hxgep); 28013dec9fcdSqs if (status != HXGE_OK) { 28023dec9fcdSqs mutex_exit(hxgep->genlock); 28033dec9fcdSqs return (ENXIO); 28043dec9fcdSqs } 28053dec9fcdSqs } 28063dec9fcdSqs 28073dec9fcdSqs mmac_info = &hxgep->hxge_mmac_info; 28083dec9fcdSqs if (slot <= 0 || slot >= mmac_info->num_mmac) { 28093dec9fcdSqs mutex_exit(hxgep->genlock); 28103dec9fcdSqs return (EINVAL); 28113dec9fcdSqs } 28123dec9fcdSqs 28133dec9fcdSqs if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 28143dec9fcdSqs if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, 28153dec9fcdSqs slot)) == 0) { 28163dec9fcdSqs bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 28173dec9fcdSqs ETHERADDRL); 28183dec9fcdSqs hxge_mmac_kstat_update(hxgep, slot); 28193dec9fcdSqs } 28203dec9fcdSqs } else { 28213dec9fcdSqs err = EINVAL; 28223dec9fcdSqs } 28233dec9fcdSqs 28243dec9fcdSqs mutex_exit(hxgep->genlock); 28253dec9fcdSqs return (err); 28263dec9fcdSqs } 28273dec9fcdSqs 28283dec9fcdSqs /* 28293dec9fcdSqs * static int 28303dec9fcdSqs * hxge_m_mmac_get() - Get the MAC address and other information 28313dec9fcdSqs * related to the slot. mma_flags should be set to 0 in the call. 28323dec9fcdSqs * Note: although kstat shows MAC address as zero when a slot is 28333dec9fcdSqs * not used, Crossbow expects hxge_m_mmac_get to copy factory MAC 28343dec9fcdSqs * to the caller as long as the slot is not using a user MAC address. 28353dec9fcdSqs * The following table shows the rules, 28363dec9fcdSqs * 28373dec9fcdSqs * USED VENDOR mma_addr 28383dec9fcdSqs * ------------------------------------------------------------ 28393dec9fcdSqs * (1) Slot uses a user MAC: yes no user MAC 28403dec9fcdSqs * (2) Slot uses a factory MAC: yes yes factory MAC 28413dec9fcdSqs * (3) Slot is not used but is 28423dec9fcdSqs * factory MAC capable: no yes factory MAC 28433dec9fcdSqs * (4) Slot is not used and is 28443dec9fcdSqs * not factory MAC capable: no no 0 28453dec9fcdSqs * ------------------------------------------------------------ 28463dec9fcdSqs */ 28473dec9fcdSqs int 28483dec9fcdSqs hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 28493dec9fcdSqs { 28503dec9fcdSqs hxge_t *hxgep = arg; 28513dec9fcdSqs mac_addr_slot_t slot; 28523dec9fcdSqs hxge_mmac_t *mmac_info; 28533dec9fcdSqs hxge_status_t status; 28543dec9fcdSqs 28553dec9fcdSqs slot = maddr->mma_slot; 28563dec9fcdSqs 28573dec9fcdSqs mutex_enter(hxgep->genlock); 28583dec9fcdSqs 28593dec9fcdSqs /* 28603dec9fcdSqs * Make sure that hxge is initialized, if _start() has 28613dec9fcdSqs * not been called. 28623dec9fcdSqs */ 28633dec9fcdSqs if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 28643dec9fcdSqs status = hxge_init(hxgep); 28653dec9fcdSqs if (status != HXGE_OK) { 28663dec9fcdSqs mutex_exit(hxgep->genlock); 28673dec9fcdSqs return (ENXIO); 28683dec9fcdSqs } 28693dec9fcdSqs } 28703dec9fcdSqs 28713dec9fcdSqs mmac_info = &hxgep->hxge_mmac_info; 28723dec9fcdSqs if (slot <= 0 || slot >= mmac_info->num_mmac) { 28733dec9fcdSqs mutex_exit(hxgep->genlock); 28743dec9fcdSqs return (EINVAL); 28753dec9fcdSqs } 28763dec9fcdSqs 28773dec9fcdSqs maddr->mma_flags = 0; 28783dec9fcdSqs if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 28793dec9fcdSqs maddr->mma_flags |= MMAC_SLOT_USED; 28803dec9fcdSqs bcopy(mmac_info->mac_pool[slot].addr, 28813dec9fcdSqs maddr->mma_addr, ETHERADDRL); 28823dec9fcdSqs maddr->mma_addrlen = ETHERADDRL; 28833dec9fcdSqs } 28843dec9fcdSqs 28853dec9fcdSqs mutex_exit(hxgep->genlock); 28863dec9fcdSqs return (0); 28873dec9fcdSqs } 28883dec9fcdSqs 28893dec9fcdSqs /*ARGSUSED*/ 28903dec9fcdSqs boolean_t 28913dec9fcdSqs hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 28923dec9fcdSqs { 28933dec9fcdSqs p_hxge_t hxgep = (p_hxge_t)arg; 28943dec9fcdSqs uint32_t *txflags = cap_data; 28953dec9fcdSqs multiaddress_capab_t *mmacp = cap_data; 28963dec9fcdSqs 28973dec9fcdSqs switch (cap) { 28983dec9fcdSqs case MAC_CAPAB_HCKSUM: 28993dec9fcdSqs *txflags = HCKSUM_INET_PARTIAL; 29003dec9fcdSqs break; 29013dec9fcdSqs 29023dec9fcdSqs case MAC_CAPAB_POLL: 29033dec9fcdSqs /* 29043dec9fcdSqs * There's nothing for us to fill in, simply returning B_TRUE 29053dec9fcdSqs * stating that we support polling is sufficient. 29063dec9fcdSqs */ 29073dec9fcdSqs break; 29083dec9fcdSqs 29093dec9fcdSqs case MAC_CAPAB_MULTIADDRESS: 29103dec9fcdSqs /* 29113dec9fcdSqs * The number of MAC addresses made available by 29123dec9fcdSqs * this capability is one less than the total as 29133dec9fcdSqs * the primary address in slot 0 is counted in 29143dec9fcdSqs * the total. 29153dec9fcdSqs */ 29163dec9fcdSqs mmacp->maddr_naddr = PFC_N_MAC_ADDRESSES - 1; 29173dec9fcdSqs mmacp->maddr_naddrfree = hxgep->hxge_mmac_info.naddrfree; 29183dec9fcdSqs mmacp->maddr_flag = 0; /* No multiple factory macs */ 29193dec9fcdSqs mmacp->maddr_handle = hxgep; 29203dec9fcdSqs mmacp->maddr_add = hxge_m_mmac_add; 29213dec9fcdSqs mmacp->maddr_remove = hxge_m_mmac_remove; 29223dec9fcdSqs mmacp->maddr_modify = hxge_m_mmac_modify; 29233dec9fcdSqs mmacp->maddr_get = hxge_m_mmac_get; 29243dec9fcdSqs mmacp->maddr_reserve = NULL; /* No multiple factory macs */ 29253dec9fcdSqs break; 29263dec9fcdSqs default: 29273dec9fcdSqs return (B_FALSE); 29283dec9fcdSqs } 29293dec9fcdSqs return (B_TRUE); 29303dec9fcdSqs } 29313dec9fcdSqs 2932*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static boolean_t 2933*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_param_locked(mac_prop_id_t pr_num) 2934*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 2935*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 2936*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * All adv_* parameters are locked (read-only) while 2937*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * the device is in any sort of loopback mode ... 2938*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 2939*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States switch (pr_num) { 2940*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000FDX_CAP: 2941*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000FDX_CAP: 2942*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000HDX_CAP: 2943*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000HDX_CAP: 2944*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100FDX_CAP: 2945*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100FDX_CAP: 2946*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100HDX_CAP: 2947*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100HDX_CAP: 2948*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10FDX_CAP: 2949*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10FDX_CAP: 2950*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10HDX_CAP: 2951*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10HDX_CAP: 2952*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_AUTONEG: 2953*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_FLOWCTRL: 2954*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (B_TRUE); 2955*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 2956*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (B_FALSE); 2957*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 2958*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 2959*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 2960*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * callback functions for set/get of properties 2961*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 2962*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int 2963*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 2964*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_valsize, const void *pr_val) 2965*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 2966*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_t *hxgep = barg; 2967*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_stats_t statsp; 2968*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int err = 0; 2969*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint32_t new_mtu, old_framesize, new_framesize; 2970*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 2971*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop")); 2972*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 2973*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp = hxgep->statsp; 2974*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mutex_enter(hxgep->genlock); 2975*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (statsp->port_stats.lb_mode != hxge_lb_normal && 2976*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_param_locked(pr_num)) { 2977*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 2978*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * All adv_* parameters are locked (read-only) 2979*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * while the device is in any sort of loopback mode. 2980*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 2981*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 2982*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_setprop: loopback mode: read only")); 2983*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mutex_exit(hxgep->genlock); 2984*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EBUSY); 2985*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 2986*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 2987*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States switch (pr_num) { 2988*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 2989*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * These properties are either not exist or read only 2990*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 2991*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000FDX_CAP: 2992*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100FDX_CAP: 2993*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10FDX_CAP: 2994*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000HDX_CAP: 2995*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100HDX_CAP: 2996*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10HDX_CAP: 2997*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000FDX_CAP: 2998*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000HDX_CAP: 2999*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100FDX_CAP: 3000*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100HDX_CAP: 3001*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10FDX_CAP: 3002*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10HDX_CAP: 3003*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_STATUS: 3004*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_SPEED: 3005*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_DUPLEX: 3006*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_AUTONEG: 3007*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 3008*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * Flow control is handled in the shared domain and 3009*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * it is readonly here. 3010*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 3011*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_FLOWCTRL: 3012*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3013*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3014*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_setprop: read only property %d", 3015*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States pr_num)); 3016*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3017*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3018*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_MTU: 3019*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) { 3020*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EBUSY; 3021*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3022*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3023*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3024*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 3025*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3026*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_setprop: set MTU: %d", new_mtu)); 3027*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3028*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States new_framesize = new_mtu + MTU_TO_FRAME_SIZE; 3029*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (new_framesize == hxgep->vmac.maxframesize) { 3030*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = 0; 3031*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3032*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3033*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3034*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (new_framesize < MIN_FRAME_SIZE || 3035*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States new_framesize > MAX_FRAME_SIZE) { 3036*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3037*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3038*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3039*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3040*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States old_framesize = hxgep->vmac.maxframesize; 3041*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->vmac.maxframesize = (uint16_t)new_framesize; 3042*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3043*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (hxge_vmac_set_framesize(hxgep)) { 3044*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->vmac.maxframesize = 3045*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (uint16_t)old_framesize; 3046*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3047*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3048*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3049*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3050*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = mac_maxsdu_update(hxgep->mach, new_mtu); 3051*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (err) { 3052*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxgep->vmac.maxframesize = 3053*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (uint16_t)old_framesize; 3054*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) hxge_vmac_set_framesize(hxgep); 3055*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3056*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3057*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3058*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_setprop: set MTU: %d maxframe %d", 3059*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States new_mtu, hxgep->vmac.maxframesize)); 3060*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3061*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3062*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_PRIVATE: 3063*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3064*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_setprop: private property")); 3065*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize, 3066*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States pr_val); 3067*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3068*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3069*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States default: 3070*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = ENOTSUP; 3071*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3072*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3073*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3074*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mutex_exit(hxgep->genlock); 3075*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3076*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3077*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "<== hxge_m_setprop (return %d)", err)); 3078*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3079*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3080*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3081*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3082*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* ARGSUSED */ 3083*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int 3084*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 3085*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States void *pr_val) 3086*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 3087*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int err = 0; 3088*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States link_flowctrl_t fl; 3089*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3090*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States switch (pr_num) { 3091*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_DUPLEX: 3092*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States *(uint8_t *)pr_val = 2; 3093*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3094*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_AUTONEG: 3095*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States *(uint8_t *)pr_val = 0; 3096*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3097*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_FLOWCTRL: 3098*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize < sizeof (link_flowctrl_t)) 3099*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3100*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States fl = LINK_FLOWCTRL_TX; 3101*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bcopy(&fl, pr_val, sizeof (fl)); 3102*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3103*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States default: 3104*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = ENOTSUP; 3105*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3106*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3107*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3108*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3109*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3110*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int 3111*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 3112*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_flags, uint_t pr_valsize, void *pr_val) 3113*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 3114*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_t *hxgep = barg; 3115*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_stats_t statsp = hxgep->statsp; 3116*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int err = 0; 3117*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States link_flowctrl_t fl; 3118*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint64_t tmp = 0; 3119*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States link_state_t ls; 3120*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3121*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3122*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_getprop: pr_num %d", pr_num)); 3123*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3124*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize == 0) 3125*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3126*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3127*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if ((pr_flags & MAC_PROP_DEFAULT) && (pr_num != MAC_PROP_PRIVATE)) { 3128*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_get_def_val(hxgep, pr_num, pr_valsize, pr_val); 3129*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3130*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3131*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3132*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bzero(pr_val, pr_valsize); 3133*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States switch (pr_num) { 3134*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_DUPLEX: 3135*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 3136*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3137*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_m_getprop: duplex mode %d", 3138*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States *(uint8_t *)pr_val)); 3139*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3140*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3141*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_SPEED: 3142*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize < sizeof (uint64_t)) 3143*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3144*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States tmp = statsp->mac_stats.link_speed * 1000000ull; 3145*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bcopy(&tmp, pr_val, sizeof (tmp)); 3146*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3147*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3148*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_STATUS: 3149*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize < sizeof (link_state_t)) 3150*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3151*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (!statsp->mac_stats.link_up) 3152*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States ls = LINK_STATE_DOWN; 3153*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States else 3154*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States ls = LINK_STATE_UP; 3155*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bcopy(&ls, pr_val, sizeof (ls)); 3156*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3157*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3158*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_FLOWCTRL: 3159*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 3160*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * Flow control is supported by the shared domain and 3161*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * it is currently transmit only 3162*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 3163*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize < sizeof (link_flowctrl_t)) 3164*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3165*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States fl = LINK_FLOWCTRL_TX; 3166*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States bcopy(&fl, pr_val, sizeof (fl)); 3167*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3168*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_AUTONEG: 3169*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 10G link only and it is not negotiable */ 3170*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States *(uint8_t *)pr_val = 0; 3171*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3172*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000FDX_CAP: 3173*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100FDX_CAP: 3174*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10FDX_CAP: 3175*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_1000HDX_CAP: 3176*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_100HDX_CAP: 3177*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_ADV_10HDX_CAP: 3178*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000FDX_CAP: 3179*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100FDX_CAP: 3180*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10FDX_CAP: 3181*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_1000HDX_CAP: 3182*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_100HDX_CAP: 3183*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_EN_10HDX_CAP: 3184*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = ENOTSUP; 3185*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3186*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3187*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States case MAC_PROP_PRIVATE: 3188*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_get_priv_prop(hxgep, pr_name, pr_flags, 3189*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States pr_valsize, pr_val); 3190*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3191*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States default: 3192*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3193*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States break; 3194*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3195*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3196*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop")); 3197*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3198*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3199*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3200*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3201*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* ARGSUSED */ 3202*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int 3203*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize, 3204*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States const void *pr_val) 3205*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 3206*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_param_t param_arr = hxgep->param_arr; 3207*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int err = 0; 3208*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3209*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3210*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val)); 3211*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3212*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_val == NULL) { 3213*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (EINVAL); 3214*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3216*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Blanking */ 3217*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3218*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_rx_intr_time(hxgep, NULL, NULL, 3219*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_time]); 3220*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3221*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL, 3222*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 3223*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3224*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Classification */ 3225*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 3226*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3227*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 3228*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 3229*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3230*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 3231*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 3232*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3233*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 3234*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 3235*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3236*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 3237*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 3238*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3239*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 3240*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 3241*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3242*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 3243*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 3244*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3245*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 3246*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3247*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3248*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 3249*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 3250*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3251*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3252*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3253*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3254*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "<== hxge_set_priv_prop: err %d", err)); 3255*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3256*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3257*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3258*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3259*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int 3260*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_flags, 3261*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t pr_valsize, void *pr_val) 3262*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 3263*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_param_t param_arr = hxgep->param_arr; 3264*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States char valstr[MAXNAMELEN]; 3265*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int err = 0; 3266*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint_t strsize; 3267*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States int value = 0; 3268*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3269*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3270*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "==> hxge_get_priv_prop: property %s", pr_name)); 3271*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3272*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_flags & MAC_PROP_DEFAULT) { 3273*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Receive Interrupt Blanking Parameters */ 3274*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3275*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = RXDMA_RCR_TO_DEFAULT; 3276*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3277*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = RXDMA_RCR_PTHRES_DEFAULT; 3278*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3279*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Classification and Load Distribution Configuration */ 3280*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 || 3281*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv4_udp") == 0 || 3282*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv4_ah") == 0 || 3283*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 || 3284*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 || 3285*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv6_udp") == 0 || 3286*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv6_ah") == 0 || 3287*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3288*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = HXGE_CLASS_TCAM_LOOKUP; 3289*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 3290*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3291*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3292*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 3293*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Receive Interrupt Blanking Parameters */ 3294*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3295*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = hxgep->intr_timeout; 3296*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3297*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = hxgep->intr_threshold; 3298*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3299*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Classification and Load Distribution Configuration */ 3300*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 3301*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3302*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 3303*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3304*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv4_tcp].value; 3305*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 3306*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3307*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 3308*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3309*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv4_udp].value; 3310*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 3311*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3312*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 3313*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3314*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv4_ah].value; 3315*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 3316*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3317*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 3318*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3319*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv4_sctp].value; 3320*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 3321*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3322*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 3323*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3324*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv6_tcp].value; 3325*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 3326*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3327*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 3328*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3329*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv6_udp].value; 3330*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 3331*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3332*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 3333*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3334*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv6_ah].value; 3335*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3336*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3337*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 3338*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3339*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States value = (int)param_arr[param_class_opt_ipv6_sctp].value; 3340*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 3341*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = EINVAL; 3342*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3343*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3344*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3345*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (err == 0) { 3346*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) snprintf(valstr, sizeof (valstr), "0x%x", value); 3347*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3348*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States strsize = (uint_t)strlen(valstr); 3349*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (pr_valsize < strsize) { 3350*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States err = ENOBUFS; 3351*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 3352*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) strlcpy(pr_val, valstr, pr_valsize); 3353*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3354*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 3355*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3356*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3357*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "<== hxge_get_priv_prop: return %d", err)); 3358*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 3359*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States return (err); 3360*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 33613dec9fcdSqs /* 33623dec9fcdSqs * Module loading and removing entry points. 33633dec9fcdSqs */ 33643dec9fcdSqs DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach, 33653dec9fcdSqs nodev, NULL, D_MP, NULL); 33663dec9fcdSqs 33673dec9fcdSqs extern struct mod_ops mod_driverops; 33683dec9fcdSqs 33693dec9fcdSqs #define HXGE_DESC_VER "HXGE 10Gb Ethernet Driver" 33703dec9fcdSqs 33713dec9fcdSqs /* 33723dec9fcdSqs * Module linkage information for the kernel. 33733dec9fcdSqs */ 33743dec9fcdSqs static struct modldrv hxge_modldrv = { 33753dec9fcdSqs &mod_driverops, 33763dec9fcdSqs HXGE_DESC_VER, 33773dec9fcdSqs &hxge_dev_ops 33783dec9fcdSqs }; 33793dec9fcdSqs 33803dec9fcdSqs static struct modlinkage modlinkage = { 33813dec9fcdSqs MODREV_1, (void *) &hxge_modldrv, NULL 33823dec9fcdSqs }; 33833dec9fcdSqs 33843dec9fcdSqs int 33853dec9fcdSqs _init(void) 33863dec9fcdSqs { 33873dec9fcdSqs int status; 33883dec9fcdSqs 33893dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 33903dec9fcdSqs mac_init_ops(&hxge_dev_ops, "hxge"); 33913dec9fcdSqs status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0); 33923dec9fcdSqs if (status != 0) { 33933dec9fcdSqs HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 33943dec9fcdSqs "failed to init device soft state")); 33953dec9fcdSqs mac_fini_ops(&hxge_dev_ops); 33963dec9fcdSqs goto _init_exit; 33973dec9fcdSqs } 33983dec9fcdSqs 33993dec9fcdSqs status = mod_install(&modlinkage); 34003dec9fcdSqs if (status != 0) { 34013dec9fcdSqs ddi_soft_state_fini(&hxge_list); 34023dec9fcdSqs HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed")); 34033dec9fcdSqs goto _init_exit; 34043dec9fcdSqs } 34053dec9fcdSqs 34063dec9fcdSqs MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL); 34073dec9fcdSqs 34083dec9fcdSqs _init_exit: 34093dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 34103dec9fcdSqs 34113dec9fcdSqs return (status); 34123dec9fcdSqs } 34133dec9fcdSqs 34143dec9fcdSqs int 34153dec9fcdSqs _fini(void) 34163dec9fcdSqs { 34173dec9fcdSqs int status; 34183dec9fcdSqs 34193dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 34203dec9fcdSqs 34213dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 34223dec9fcdSqs 34233dec9fcdSqs if (hxge_mblks_pending) 34243dec9fcdSqs return (EBUSY); 34253dec9fcdSqs 34263dec9fcdSqs status = mod_remove(&modlinkage); 34273dec9fcdSqs if (status != DDI_SUCCESS) { 34283dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, 34293dec9fcdSqs "Module removal failed 0x%08x", status)); 34303dec9fcdSqs goto _fini_exit; 34313dec9fcdSqs } 34323dec9fcdSqs 34333dec9fcdSqs mac_fini_ops(&hxge_dev_ops); 34343dec9fcdSqs 34353dec9fcdSqs ddi_soft_state_fini(&hxge_list); 34363dec9fcdSqs 34373dec9fcdSqs MUTEX_DESTROY(&hxge_common_lock); 34383dec9fcdSqs 34393dec9fcdSqs _fini_exit: 34403dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 34413dec9fcdSqs 34423dec9fcdSqs return (status); 34433dec9fcdSqs } 34443dec9fcdSqs 34453dec9fcdSqs int 34463dec9fcdSqs _info(struct modinfo *modinfop) 34473dec9fcdSqs { 34483dec9fcdSqs int status; 34493dec9fcdSqs 34503dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 34513dec9fcdSqs status = mod_info(&modlinkage, modinfop); 34523dec9fcdSqs HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 34533dec9fcdSqs 34543dec9fcdSqs return (status); 34553dec9fcdSqs } 34563dec9fcdSqs 34573dec9fcdSqs /*ARGSUSED*/ 34583dec9fcdSqs hxge_status_t 34593dec9fcdSqs hxge_add_intrs(p_hxge_t hxgep) 34603dec9fcdSqs { 34613dec9fcdSqs int intr_types; 34623dec9fcdSqs int type = 0; 34633dec9fcdSqs int ddi_status = DDI_SUCCESS; 34643dec9fcdSqs hxge_status_t status = HXGE_OK; 34653dec9fcdSqs 34663dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs")); 34673dec9fcdSqs 34683dec9fcdSqs hxgep->hxge_intr_type.intr_registered = B_FALSE; 34693dec9fcdSqs hxgep->hxge_intr_type.intr_enabled = B_FALSE; 34703dec9fcdSqs hxgep->hxge_intr_type.msi_intx_cnt = 0; 34713dec9fcdSqs hxgep->hxge_intr_type.intr_added = 0; 34723dec9fcdSqs hxgep->hxge_intr_type.niu_msi_enable = B_FALSE; 34733dec9fcdSqs hxgep->hxge_intr_type.intr_type = 0; 34743dec9fcdSqs 34753dec9fcdSqs if (hxge_msi_enable) { 34763dec9fcdSqs hxgep->hxge_intr_type.niu_msi_enable = B_TRUE; 34773dec9fcdSqs } 34783dec9fcdSqs 34793dec9fcdSqs /* Get the supported interrupt types */ 34803dec9fcdSqs if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types)) 34813dec9fcdSqs != DDI_SUCCESS) { 34823dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: " 34833dec9fcdSqs "ddi_intr_get_supported_types failed: status 0x%08x", 34843dec9fcdSqs ddi_status)); 34853dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 34863dec9fcdSqs } 34873dec9fcdSqs 34883dec9fcdSqs hxgep->hxge_intr_type.intr_types = intr_types; 34893dec9fcdSqs 34903dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 34913dec9fcdSqs "ddi_intr_get_supported_types: 0x%08x", intr_types)); 34923dec9fcdSqs 34933dec9fcdSqs /* 34943dec9fcdSqs * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable: 34953dec9fcdSqs * (1): 1 - MSI 34963dec9fcdSqs * (2): 2 - MSI-X 34973dec9fcdSqs * others - FIXED 34983dec9fcdSqs */ 34993dec9fcdSqs switch (hxge_msi_enable) { 35003dec9fcdSqs default: 35013dec9fcdSqs type = DDI_INTR_TYPE_FIXED; 35023dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 35033dec9fcdSqs "use fixed (intx emulation) type %08x", type)); 35043dec9fcdSqs break; 35053dec9fcdSqs 35063dec9fcdSqs case 2: 35073dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 35083dec9fcdSqs "ddi_intr_get_supported_types: 0x%08x", intr_types)); 35093dec9fcdSqs if (intr_types & DDI_INTR_TYPE_MSIX) { 35103dec9fcdSqs type = DDI_INTR_TYPE_MSIX; 35113dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 35123dec9fcdSqs "==> hxge_add_intrs: " 35133dec9fcdSqs "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 35143dec9fcdSqs } else if (intr_types & DDI_INTR_TYPE_MSI) { 35153dec9fcdSqs type = DDI_INTR_TYPE_MSI; 35163dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 35173dec9fcdSqs "==> hxge_add_intrs: " 35183dec9fcdSqs "ddi_intr_get_supported_types: MSI 0x%08x", type)); 35193dec9fcdSqs } else if (intr_types & DDI_INTR_TYPE_FIXED) { 35203dec9fcdSqs type = DDI_INTR_TYPE_FIXED; 35213dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 35223dec9fcdSqs "ddi_intr_get_supported_types: MSXED0x%08x", type)); 35233dec9fcdSqs } 35243dec9fcdSqs break; 35253dec9fcdSqs 35263dec9fcdSqs case 1: 35273dec9fcdSqs if (intr_types & DDI_INTR_TYPE_MSI) { 35283dec9fcdSqs type = DDI_INTR_TYPE_MSI; 35293dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 35303dec9fcdSqs "==> hxge_add_intrs: " 35313dec9fcdSqs "ddi_intr_get_supported_types: MSI 0x%08x", type)); 35323dec9fcdSqs } else if (intr_types & DDI_INTR_TYPE_MSIX) { 35333dec9fcdSqs type = DDI_INTR_TYPE_MSIX; 35343dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 35353dec9fcdSqs "==> hxge_add_intrs: " 35363dec9fcdSqs "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 35373dec9fcdSqs } else if (intr_types & DDI_INTR_TYPE_FIXED) { 35383dec9fcdSqs type = DDI_INTR_TYPE_FIXED; 35393dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 35403dec9fcdSqs "==> hxge_add_intrs: " 35413dec9fcdSqs "ddi_intr_get_supported_types: MSXED0x%08x", type)); 35423dec9fcdSqs } 35433dec9fcdSqs } 35443dec9fcdSqs 35453dec9fcdSqs hxgep->hxge_intr_type.intr_type = type; 35463dec9fcdSqs if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 35473dec9fcdSqs type == DDI_INTR_TYPE_FIXED) && 35483dec9fcdSqs hxgep->hxge_intr_type.niu_msi_enable) { 35493dec9fcdSqs if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) { 35503dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35513dec9fcdSqs " hxge_add_intrs: " 35523dec9fcdSqs " hxge_add_intrs_adv failed: status 0x%08x", 35533dec9fcdSqs status)); 35543dec9fcdSqs return (status); 35553dec9fcdSqs } else { 35563dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: " 35573dec9fcdSqs "interrupts registered : type %d", type)); 35583dec9fcdSqs hxgep->hxge_intr_type.intr_registered = B_TRUE; 35593dec9fcdSqs 35603dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 35613dec9fcdSqs "\nAdded advanced hxge add_intr_adv " 35623dec9fcdSqs "intr type 0x%x\n", type)); 35633dec9fcdSqs 35643dec9fcdSqs return (status); 35653dec9fcdSqs } 35663dec9fcdSqs } 35673dec9fcdSqs 35683dec9fcdSqs if (!hxgep->hxge_intr_type.intr_registered) { 35693dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35703dec9fcdSqs "==> hxge_add_intrs: failed to register interrupts")); 35713dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 35723dec9fcdSqs } 35733dec9fcdSqs 35743dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs")); 35753dec9fcdSqs 35763dec9fcdSqs return (status); 35773dec9fcdSqs } 35783dec9fcdSqs 35793dec9fcdSqs /*ARGSUSED*/ 35803dec9fcdSqs static hxge_status_t 35813dec9fcdSqs hxge_add_soft_intrs(p_hxge_t hxgep) 35823dec9fcdSqs { 35833dec9fcdSqs int ddi_status = DDI_SUCCESS; 35843dec9fcdSqs hxge_status_t status = HXGE_OK; 35853dec9fcdSqs 35863dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_soft_intrs")); 35873dec9fcdSqs 35883dec9fcdSqs hxgep->resched_id = NULL; 35893dec9fcdSqs hxgep->resched_running = B_FALSE; 35903dec9fcdSqs ddi_status = ddi_add_softintr(hxgep->dip, DDI_SOFTINT_LOW, 35913dec9fcdSqs &hxgep->resched_id, NULL, NULL, hxge_reschedule, (caddr_t)hxgep); 35923dec9fcdSqs if (ddi_status != DDI_SUCCESS) { 35933dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_soft_intrs: " 35943dec9fcdSqs "ddi_add_softintrs failed: status 0x%08x", ddi_status)); 35953dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 35963dec9fcdSqs } 35973dec9fcdSqs 35983dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_ddi_add_soft_intrs")); 35993dec9fcdSqs 36003dec9fcdSqs return (status); 36013dec9fcdSqs } 36023dec9fcdSqs 36033dec9fcdSqs /*ARGSUSED*/ 36043dec9fcdSqs static hxge_status_t 36053dec9fcdSqs hxge_add_intrs_adv(p_hxge_t hxgep) 36063dec9fcdSqs { 36073dec9fcdSqs int intr_type; 36083dec9fcdSqs p_hxge_intr_t intrp; 36093dec9fcdSqs hxge_status_t status; 36103dec9fcdSqs 36113dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv")); 36123dec9fcdSqs 36133dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 36143dec9fcdSqs intr_type = intrp->intr_type; 36153dec9fcdSqs 36163dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x", 36173dec9fcdSqs intr_type)); 36183dec9fcdSqs 36193dec9fcdSqs switch (intr_type) { 36203dec9fcdSqs case DDI_INTR_TYPE_MSI: /* 0x2 */ 36213dec9fcdSqs case DDI_INTR_TYPE_MSIX: /* 0x4 */ 36223dec9fcdSqs status = hxge_add_intrs_adv_type(hxgep, intr_type); 36233dec9fcdSqs break; 36243dec9fcdSqs 36253dec9fcdSqs case DDI_INTR_TYPE_FIXED: /* 0x1 */ 36263dec9fcdSqs status = hxge_add_intrs_adv_type_fix(hxgep, intr_type); 36273dec9fcdSqs break; 36283dec9fcdSqs 36293dec9fcdSqs default: 36303dec9fcdSqs status = HXGE_ERROR; 36313dec9fcdSqs break; 36323dec9fcdSqs } 36333dec9fcdSqs 36343dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv")); 36353dec9fcdSqs 36363dec9fcdSqs return (status); 36373dec9fcdSqs } 36383dec9fcdSqs 36393dec9fcdSqs /*ARGSUSED*/ 36403dec9fcdSqs static hxge_status_t 36413dec9fcdSqs hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type) 36423dec9fcdSqs { 36433dec9fcdSqs dev_info_t *dip = hxgep->dip; 36443dec9fcdSqs p_hxge_ldg_t ldgp; 36453dec9fcdSqs p_hxge_intr_t intrp; 36463dec9fcdSqs uint_t *inthandler; 36473dec9fcdSqs void *arg1, *arg2; 36483dec9fcdSqs int behavior; 36493dec9fcdSqs int nintrs, navail; 36503dec9fcdSqs int nactual, nrequired; 36513dec9fcdSqs int inum = 0; 36523dec9fcdSqs int loop = 0; 36533dec9fcdSqs int x, y; 36543dec9fcdSqs int ddi_status = DDI_SUCCESS; 36553dec9fcdSqs hxge_status_t status = HXGE_OK; 36563dec9fcdSqs 36573dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type")); 36583dec9fcdSqs 36593dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 36603dec9fcdSqs 36613dec9fcdSqs ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 36623dec9fcdSqs if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 36633dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36643dec9fcdSqs "ddi_intr_get_nintrs() failed, status: 0x%x%, " 36653dec9fcdSqs "nintrs: %d", ddi_status, nintrs)); 36663dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 36673dec9fcdSqs } 36683dec9fcdSqs 36693dec9fcdSqs ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 36703dec9fcdSqs if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 36713dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36723dec9fcdSqs "ddi_intr_get_navail() failed, status: 0x%x%, " 36733dec9fcdSqs "nintrs: %d", ddi_status, navail)); 36743dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 36753dec9fcdSqs } 36763dec9fcdSqs 36773dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 36783dec9fcdSqs "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d", 36793dec9fcdSqs int_type, nintrs, navail)); 36803dec9fcdSqs 36813dec9fcdSqs if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 36823dec9fcdSqs /* MSI must be power of 2 */ 36833dec9fcdSqs if ((navail & 16) == 16) { 36843dec9fcdSqs navail = 16; 36853dec9fcdSqs } else if ((navail & 8) == 8) { 36863dec9fcdSqs navail = 8; 36873dec9fcdSqs } else if ((navail & 4) == 4) { 36883dec9fcdSqs navail = 4; 36893dec9fcdSqs } else if ((navail & 2) == 2) { 36903dec9fcdSqs navail = 2; 36913dec9fcdSqs } else { 36923dec9fcdSqs navail = 1; 36933dec9fcdSqs } 36943dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 36953dec9fcdSqs "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 36963dec9fcdSqs "navail %d", nintrs, navail)); 36973dec9fcdSqs } 36983dec9fcdSqs 36993dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37003dec9fcdSqs "requesting: intr type %d nintrs %d, navail %d", 37013dec9fcdSqs int_type, nintrs, navail)); 37023dec9fcdSqs 37033dec9fcdSqs behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 37043dec9fcdSqs DDI_INTR_ALLOC_NORMAL); 37053dec9fcdSqs intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 37063dec9fcdSqs intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP); 37073dec9fcdSqs 37083dec9fcdSqs ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 37093dec9fcdSqs navail, &nactual, behavior); 37103dec9fcdSqs if (ddi_status != DDI_SUCCESS || nactual == 0) { 37113dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37123dec9fcdSqs " ddi_intr_alloc() failed: %d", ddi_status)); 37133dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 37143dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 37153dec9fcdSqs } 37163dec9fcdSqs 37173dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37183dec9fcdSqs "ddi_intr_alloc() returned: navail %d nactual %d", 37193dec9fcdSqs navail, nactual)); 37203dec9fcdSqs 37213dec9fcdSqs if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 37223dec9fcdSqs (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 37233dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37243dec9fcdSqs " ddi_intr_get_pri() failed: %d", ddi_status)); 37253dec9fcdSqs /* Free already allocated interrupts */ 37263dec9fcdSqs for (y = 0; y < nactual; y++) { 37273dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 37283dec9fcdSqs } 37293dec9fcdSqs 37303dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 37313dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 37323dec9fcdSqs } 37333dec9fcdSqs 37343dec9fcdSqs nrequired = 0; 37353dec9fcdSqs status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 37363dec9fcdSqs if (status != HXGE_OK) { 37373dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37383dec9fcdSqs "hxge_add_intrs_adv_typ:hxge_ldgv_init " 37393dec9fcdSqs "failed: 0x%x", status)); 37403dec9fcdSqs /* Free already allocated interrupts */ 37413dec9fcdSqs for (y = 0; y < nactual; y++) { 37423dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 37433dec9fcdSqs } 37443dec9fcdSqs 37453dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 37463dec9fcdSqs return (status); 37473dec9fcdSqs } 37483dec9fcdSqs 37493dec9fcdSqs ldgp = hxgep->ldgvp->ldgp; 37503dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37513dec9fcdSqs "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual)); 37523dec9fcdSqs 37533dec9fcdSqs if (nactual < nrequired) 37543dec9fcdSqs loop = nactual; 37553dec9fcdSqs else 37563dec9fcdSqs loop = nrequired; 37573dec9fcdSqs 37583dec9fcdSqs for (x = 0; x < loop; x++, ldgp++) { 37593dec9fcdSqs ldgp->vector = (uint8_t)x; 37603dec9fcdSqs arg1 = ldgp->ldvp; 37613dec9fcdSqs arg2 = hxgep; 37623dec9fcdSqs if (ldgp->nldvs == 1) { 37633dec9fcdSqs inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 37643dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37653dec9fcdSqs "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 37663dec9fcdSqs "1-1 int handler (entry %d)\n", 37673dec9fcdSqs arg1, arg2, x)); 37683dec9fcdSqs } else if (ldgp->nldvs > 1) { 37693dec9fcdSqs inthandler = (uint_t *)ldgp->sys_intr_handler; 37703dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37713dec9fcdSqs "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 37723dec9fcdSqs "nldevs %d int handler (entry %d)\n", 37733dec9fcdSqs arg1, arg2, ldgp->nldvs, x)); 37743dec9fcdSqs } 37753dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 37763dec9fcdSqs "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 37773dec9fcdSqs "htable 0x%llx", x, intrp->htable[x])); 37783dec9fcdSqs 37793dec9fcdSqs if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 37803dec9fcdSqs (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 37813dec9fcdSqs DDI_SUCCESS) { 37823dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37833dec9fcdSqs "==> hxge_add_intrs_adv_type: failed #%d " 37843dec9fcdSqs "status 0x%x", x, ddi_status)); 37853dec9fcdSqs for (y = 0; y < intrp->intr_added; y++) { 37863dec9fcdSqs (void) ddi_intr_remove_handler( 37873dec9fcdSqs intrp->htable[y]); 37883dec9fcdSqs } 37893dec9fcdSqs 37903dec9fcdSqs /* Free already allocated intr */ 37913dec9fcdSqs for (y = 0; y < nactual; y++) { 37923dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 37933dec9fcdSqs } 37943dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 37953dec9fcdSqs 37963dec9fcdSqs (void) hxge_ldgv_uninit(hxgep); 37973dec9fcdSqs 37983dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 37993dec9fcdSqs } 38003dec9fcdSqs 38013dec9fcdSqs intrp->intr_added++; 38023dec9fcdSqs } 38033dec9fcdSqs intrp->msi_intx_cnt = nactual; 38043dec9fcdSqs 38053dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 38063dec9fcdSqs "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 38073dec9fcdSqs navail, nactual, intrp->msi_intx_cnt, intrp->intr_added)); 38083dec9fcdSqs 38093dec9fcdSqs (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 38103dec9fcdSqs (void) hxge_intr_ldgv_init(hxgep); 38113dec9fcdSqs 38123dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type")); 38133dec9fcdSqs 38143dec9fcdSqs return (status); 38153dec9fcdSqs } 38163dec9fcdSqs 38173dec9fcdSqs /*ARGSUSED*/ 38183dec9fcdSqs static hxge_status_t 38193dec9fcdSqs hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type) 38203dec9fcdSqs { 38213dec9fcdSqs dev_info_t *dip = hxgep->dip; 38223dec9fcdSqs p_hxge_ldg_t ldgp; 38233dec9fcdSqs p_hxge_intr_t intrp; 38243dec9fcdSqs uint_t *inthandler; 38253dec9fcdSqs void *arg1, *arg2; 38263dec9fcdSqs int behavior; 38273dec9fcdSqs int nintrs, navail; 38283dec9fcdSqs int nactual, nrequired; 38293dec9fcdSqs int inum = 0; 38303dec9fcdSqs int x, y; 38313dec9fcdSqs int ddi_status = DDI_SUCCESS; 38323dec9fcdSqs hxge_status_t status = HXGE_OK; 38333dec9fcdSqs 38343dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix")); 38353dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 38363dec9fcdSqs 38373dec9fcdSqs ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 38383dec9fcdSqs if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 38393dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 38403dec9fcdSqs "ddi_intr_get_nintrs() failed, status: 0x%x%, " 38413dec9fcdSqs "nintrs: %d", status, nintrs)); 38423dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 38433dec9fcdSqs } 38443dec9fcdSqs 38453dec9fcdSqs ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 38463dec9fcdSqs if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 38473dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38483dec9fcdSqs "ddi_intr_get_navail() failed, status: 0x%x%, " 38493dec9fcdSqs "nintrs: %d", ddi_status, navail)); 38503dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 38513dec9fcdSqs } 38523dec9fcdSqs 38533dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 38543dec9fcdSqs "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 38553dec9fcdSqs nintrs, navail)); 38563dec9fcdSqs 38573dec9fcdSqs behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 38583dec9fcdSqs DDI_INTR_ALLOC_NORMAL); 38593dec9fcdSqs intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 38603dec9fcdSqs intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 38613dec9fcdSqs ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 38623dec9fcdSqs navail, &nactual, behavior); 38633dec9fcdSqs if (ddi_status != DDI_SUCCESS || nactual == 0) { 38643dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38653dec9fcdSqs " ddi_intr_alloc() failed: %d", ddi_status)); 38663dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 38673dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 38683dec9fcdSqs } 38693dec9fcdSqs 38703dec9fcdSqs if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 38713dec9fcdSqs (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 38723dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38733dec9fcdSqs " ddi_intr_get_pri() failed: %d", ddi_status)); 38743dec9fcdSqs /* Free already allocated interrupts */ 38753dec9fcdSqs for (y = 0; y < nactual; y++) { 38763dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 38773dec9fcdSqs } 38783dec9fcdSqs 38793dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 38803dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 38813dec9fcdSqs } 38823dec9fcdSqs 38833dec9fcdSqs nrequired = 0; 38843dec9fcdSqs status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 38853dec9fcdSqs if (status != HXGE_OK) { 38863dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38873dec9fcdSqs "hxge_add_intrs_adv_type_fix:hxge_ldgv_init " 38883dec9fcdSqs "failed: 0x%x", status)); 38893dec9fcdSqs /* Free already allocated interrupts */ 38903dec9fcdSqs for (y = 0; y < nactual; y++) { 38913dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 38923dec9fcdSqs } 38933dec9fcdSqs 38943dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 38953dec9fcdSqs return (status); 38963dec9fcdSqs } 38973dec9fcdSqs 38983dec9fcdSqs ldgp = hxgep->ldgvp->ldgp; 38993dec9fcdSqs for (x = 0; x < nrequired; x++, ldgp++) { 39003dec9fcdSqs ldgp->vector = (uint8_t)x; 39013dec9fcdSqs arg1 = ldgp->ldvp; 39023dec9fcdSqs arg2 = hxgep; 39033dec9fcdSqs if (ldgp->nldvs == 1) { 39043dec9fcdSqs inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 39053dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 39063dec9fcdSqs "hxge_add_intrs_adv_type_fix: " 39073dec9fcdSqs "1-1 int handler(%d) ldg %d ldv %d " 39083dec9fcdSqs "arg1 $%p arg2 $%p\n", 39093dec9fcdSqs x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2)); 39103dec9fcdSqs } else if (ldgp->nldvs > 1) { 39113dec9fcdSqs inthandler = (uint_t *)ldgp->sys_intr_handler; 39123dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 39133dec9fcdSqs "hxge_add_intrs_adv_type_fix: " 39143dec9fcdSqs "shared ldv %d int handler(%d) ldv %d ldg %d" 39153dec9fcdSqs "arg1 0x%016llx arg2 0x%016llx\n", 39163dec9fcdSqs x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 39173dec9fcdSqs arg1, arg2)); 39183dec9fcdSqs } 39193dec9fcdSqs 39203dec9fcdSqs if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 39213dec9fcdSqs (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 39223dec9fcdSqs DDI_SUCCESS) { 39233dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 39243dec9fcdSqs "==> hxge_add_intrs_adv_type_fix: failed #%d " 39253dec9fcdSqs "status 0x%x", x, ddi_status)); 39263dec9fcdSqs for (y = 0; y < intrp->intr_added; y++) { 39273dec9fcdSqs (void) ddi_intr_remove_handler( 39283dec9fcdSqs intrp->htable[y]); 39293dec9fcdSqs } 39303dec9fcdSqs for (y = 0; y < nactual; y++) { 39313dec9fcdSqs (void) ddi_intr_free(intrp->htable[y]); 39323dec9fcdSqs } 39333dec9fcdSqs /* Free already allocated intr */ 39343dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 39353dec9fcdSqs 39363dec9fcdSqs (void) hxge_ldgv_uninit(hxgep); 39373dec9fcdSqs 39383dec9fcdSqs return (HXGE_ERROR | HXGE_DDI_FAILED); 39393dec9fcdSqs } 39403dec9fcdSqs intrp->intr_added++; 39413dec9fcdSqs } 39423dec9fcdSqs 39433dec9fcdSqs intrp->msi_intx_cnt = nactual; 39443dec9fcdSqs 39453dec9fcdSqs (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 39463dec9fcdSqs 39473dec9fcdSqs status = hxge_intr_ldgv_init(hxgep); 39483dec9fcdSqs 39493dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix")); 39503dec9fcdSqs 39513dec9fcdSqs return (status); 39523dec9fcdSqs } 39533dec9fcdSqs 39543dec9fcdSqs /*ARGSUSED*/ 39553dec9fcdSqs static void 39563dec9fcdSqs hxge_remove_intrs(p_hxge_t hxgep) 39573dec9fcdSqs { 39583dec9fcdSqs int i, inum; 39593dec9fcdSqs p_hxge_intr_t intrp; 39603dec9fcdSqs 39613dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs")); 39623dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 39633dec9fcdSqs if (!intrp->intr_registered) { 39643dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 39653dec9fcdSqs "<== hxge_remove_intrs: interrupts not registered")); 39663dec9fcdSqs return; 39673dec9fcdSqs } 39683dec9fcdSqs 39693dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced")); 39703dec9fcdSqs 39713dec9fcdSqs if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 39723dec9fcdSqs (void) ddi_intr_block_disable(intrp->htable, 39733dec9fcdSqs intrp->intr_added); 39743dec9fcdSqs } else { 39753dec9fcdSqs for (i = 0; i < intrp->intr_added; i++) { 39763dec9fcdSqs (void) ddi_intr_disable(intrp->htable[i]); 39773dec9fcdSqs } 39783dec9fcdSqs } 39793dec9fcdSqs 39803dec9fcdSqs for (inum = 0; inum < intrp->intr_added; inum++) { 39813dec9fcdSqs if (intrp->htable[inum]) { 39823dec9fcdSqs (void) ddi_intr_remove_handler(intrp->htable[inum]); 39833dec9fcdSqs } 39843dec9fcdSqs } 39853dec9fcdSqs 39863dec9fcdSqs for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 39873dec9fcdSqs if (intrp->htable[inum]) { 39883dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 39893dec9fcdSqs "hxge_remove_intrs: ddi_intr_free inum %d " 39903dec9fcdSqs "msi_intx_cnt %d intr_added %d", 39913dec9fcdSqs inum, intrp->msi_intx_cnt, intrp->intr_added)); 39923dec9fcdSqs 39933dec9fcdSqs (void) ddi_intr_free(intrp->htable[inum]); 39943dec9fcdSqs } 39953dec9fcdSqs } 39963dec9fcdSqs 39973dec9fcdSqs kmem_free(intrp->htable, intrp->intr_size); 39983dec9fcdSqs intrp->intr_registered = B_FALSE; 39993dec9fcdSqs intrp->intr_enabled = B_FALSE; 40003dec9fcdSqs intrp->msi_intx_cnt = 0; 40013dec9fcdSqs intrp->intr_added = 0; 40023dec9fcdSqs 40033dec9fcdSqs (void) hxge_ldgv_uninit(hxgep); 40043dec9fcdSqs 40053dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs")); 40063dec9fcdSqs } 40073dec9fcdSqs 40083dec9fcdSqs /*ARGSUSED*/ 40093dec9fcdSqs static void 40103dec9fcdSqs hxge_remove_soft_intrs(p_hxge_t hxgep) 40113dec9fcdSqs { 40123dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_soft_intrs")); 40133dec9fcdSqs 40143dec9fcdSqs if (hxgep->resched_id) { 40153dec9fcdSqs ddi_remove_softintr(hxgep->resched_id); 40163dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 40173dec9fcdSqs "==> hxge_remove_soft_intrs: removed")); 40183dec9fcdSqs hxgep->resched_id = NULL; 40193dec9fcdSqs } 40203dec9fcdSqs 40213dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_soft_intrs")); 40223dec9fcdSqs } 40233dec9fcdSqs 40243dec9fcdSqs /*ARGSUSED*/ 40253dec9fcdSqs void 40263dec9fcdSqs hxge_intrs_enable(p_hxge_t hxgep) 40273dec9fcdSqs { 40283dec9fcdSqs p_hxge_intr_t intrp; 40293dec9fcdSqs int i; 40303dec9fcdSqs int status; 40313dec9fcdSqs 40323dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable")); 40333dec9fcdSqs 40343dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 40353dec9fcdSqs 40363dec9fcdSqs if (!intrp->intr_registered) { 40373dec9fcdSqs HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: " 40383dec9fcdSqs "interrupts are not registered")); 40393dec9fcdSqs return; 40403dec9fcdSqs } 40413dec9fcdSqs 40423dec9fcdSqs if (intrp->intr_enabled) { 40433dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, 40443dec9fcdSqs "<== hxge_intrs_enable: already enabled")); 40453dec9fcdSqs return; 40463dec9fcdSqs } 40473dec9fcdSqs 40483dec9fcdSqs if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 40493dec9fcdSqs status = ddi_intr_block_enable(intrp->htable, 40503dec9fcdSqs intrp->intr_added); 40513dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 40523dec9fcdSqs "block enable - status 0x%x total inums #%d\n", 40533dec9fcdSqs status, intrp->intr_added)); 40543dec9fcdSqs } else { 40553dec9fcdSqs for (i = 0; i < intrp->intr_added; i++) { 40563dec9fcdSqs status = ddi_intr_enable(intrp->htable[i]); 40573dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 40583dec9fcdSqs "ddi_intr_enable:enable - status 0x%x " 40593dec9fcdSqs "total inums %d enable inum #%d\n", 40603dec9fcdSqs status, intrp->intr_added, i)); 40613dec9fcdSqs if (status == DDI_SUCCESS) { 40623dec9fcdSqs intrp->intr_enabled = B_TRUE; 40633dec9fcdSqs } 40643dec9fcdSqs } 40653dec9fcdSqs } 40663dec9fcdSqs 40673dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable")); 40683dec9fcdSqs } 40693dec9fcdSqs 40703dec9fcdSqs /*ARGSUSED*/ 40713dec9fcdSqs static void 40723dec9fcdSqs hxge_intrs_disable(p_hxge_t hxgep) 40733dec9fcdSqs { 40743dec9fcdSqs p_hxge_intr_t intrp; 40753dec9fcdSqs int i; 40763dec9fcdSqs 40773dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable")); 40783dec9fcdSqs 40793dec9fcdSqs intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 40803dec9fcdSqs 40813dec9fcdSqs if (!intrp->intr_registered) { 40823dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: " 40833dec9fcdSqs "interrupts are not registered")); 40843dec9fcdSqs return; 40853dec9fcdSqs } 40863dec9fcdSqs 40873dec9fcdSqs if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 40883dec9fcdSqs (void) ddi_intr_block_disable(intrp->htable, 40893dec9fcdSqs intrp->intr_added); 40903dec9fcdSqs } else { 40913dec9fcdSqs for (i = 0; i < intrp->intr_added; i++) { 40923dec9fcdSqs (void) ddi_intr_disable(intrp->htable[i]); 40933dec9fcdSqs } 40943dec9fcdSqs } 40953dec9fcdSqs 40963dec9fcdSqs intrp->intr_enabled = B_FALSE; 40973dec9fcdSqs HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable")); 40983dec9fcdSqs } 40993dec9fcdSqs 41003dec9fcdSqs static hxge_status_t 41013dec9fcdSqs hxge_mac_register(p_hxge_t hxgep) 41023dec9fcdSqs { 41033dec9fcdSqs mac_register_t *macp; 41043dec9fcdSqs int status; 41053dec9fcdSqs 41063dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register")); 41073dec9fcdSqs 41083dec9fcdSqs if ((macp = mac_alloc(MAC_VERSION)) == NULL) 41093dec9fcdSqs return (HXGE_ERROR); 41103dec9fcdSqs 41113dec9fcdSqs macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 41123dec9fcdSqs macp->m_driver = hxgep; 41133dec9fcdSqs macp->m_dip = hxgep->dip; 41143dec9fcdSqs macp->m_src_addr = hxgep->ouraddr.ether_addr_octet; 41153dec9fcdSqs 41163dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, 41173dec9fcdSqs "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x", 41183dec9fcdSqs macp->m_src_addr[0], 41193dec9fcdSqs macp->m_src_addr[1], 41203dec9fcdSqs macp->m_src_addr[2], 41213dec9fcdSqs macp->m_src_addr[3], 41223dec9fcdSqs macp->m_src_addr[4], 41233dec9fcdSqs macp->m_src_addr[5])); 41243dec9fcdSqs 41253dec9fcdSqs macp->m_callbacks = &hxge_m_callbacks; 41263dec9fcdSqs macp->m_min_sdu = 0; 4127*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE; 4128*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States macp->m_margin = VLAN_TAGSZ; 4129*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States macp->m_priv_props = hxge_priv_props; 4130*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States macp->m_priv_prop_count = HXGE_MAX_PRIV_PROPS; 41313dec9fcdSqs 41323dec9fcdSqs status = mac_register(macp, &hxgep->mach); 41333dec9fcdSqs mac_free(macp); 41343dec9fcdSqs 41353dec9fcdSqs if (status != 0) { 41363dec9fcdSqs cmn_err(CE_WARN, 41373dec9fcdSqs "hxge_mac_register failed (status %d instance %d)", 41383dec9fcdSqs status, hxgep->instance); 41393dec9fcdSqs return (HXGE_ERROR); 41403dec9fcdSqs } 41413dec9fcdSqs 41423dec9fcdSqs HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success " 41433dec9fcdSqs "(instance %d)", hxgep->instance)); 41443dec9fcdSqs 41453dec9fcdSqs return (HXGE_OK); 41463dec9fcdSqs } 41473dec9fcdSqs 41483dec9fcdSqs static int 41493dec9fcdSqs hxge_init_common_dev(p_hxge_t hxgep) 41503dec9fcdSqs { 41513dec9fcdSqs p_hxge_hw_list_t hw_p; 41523dec9fcdSqs dev_info_t *p_dip; 41533dec9fcdSqs 41543dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev")); 41553dec9fcdSqs 41563dec9fcdSqs p_dip = hxgep->p_dip; 41573dec9fcdSqs MUTEX_ENTER(&hxge_common_lock); 41583dec9fcdSqs 41593dec9fcdSqs /* 41603dec9fcdSqs * Loop through existing per Hydra hardware list. 41613dec9fcdSqs */ 41623dec9fcdSqs for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 41633dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 41643dec9fcdSqs "==> hxge_init_common_dev: hw_p $%p parent dip $%p", 41653dec9fcdSqs hw_p, p_dip)); 41663dec9fcdSqs if (hw_p->parent_devp == p_dip) { 41673dec9fcdSqs hxgep->hxge_hw_p = hw_p; 41683dec9fcdSqs hw_p->ndevs++; 41693dec9fcdSqs hw_p->hxge_p = hxgep; 41703dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 41713dec9fcdSqs "==> hxge_init_common_device: " 41723dec9fcdSqs "hw_p $%p parent dip $%p ndevs %d (found)", 41733dec9fcdSqs hw_p, p_dip, hw_p->ndevs)); 41743dec9fcdSqs break; 41753dec9fcdSqs } 41763dec9fcdSqs } 41773dec9fcdSqs 41783dec9fcdSqs if (hw_p == NULL) { 41793dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 41803dec9fcdSqs "==> hxge_init_common_dev: parent dip $%p (new)", p_dip)); 41813dec9fcdSqs hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP); 41823dec9fcdSqs hw_p->parent_devp = p_dip; 41833dec9fcdSqs hw_p->magic = HXGE_MAGIC; 41843dec9fcdSqs hxgep->hxge_hw_p = hw_p; 41853dec9fcdSqs hw_p->ndevs++; 41863dec9fcdSqs hw_p->hxge_p = hxgep; 41873dec9fcdSqs hw_p->next = hxge_hw_list; 41883dec9fcdSqs 41893dec9fcdSqs MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 41903dec9fcdSqs MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 41913dec9fcdSqs MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 41923dec9fcdSqs 41933dec9fcdSqs hxge_hw_list = hw_p; 41943dec9fcdSqs } 41953dec9fcdSqs MUTEX_EXIT(&hxge_common_lock); 41963dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 41973dec9fcdSqs "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 41983dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev")); 41993dec9fcdSqs 42003dec9fcdSqs return (HXGE_OK); 42013dec9fcdSqs } 42023dec9fcdSqs 42033dec9fcdSqs static void 42043dec9fcdSqs hxge_uninit_common_dev(p_hxge_t hxgep) 42053dec9fcdSqs { 42063dec9fcdSqs p_hxge_hw_list_t hw_p, h_hw_p; 42073dec9fcdSqs dev_info_t *p_dip; 42083dec9fcdSqs 42093dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev")); 42103dec9fcdSqs if (hxgep->hxge_hw_p == NULL) { 42113dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42123dec9fcdSqs "<== hxge_uninit_common_dev (no common)")); 42133dec9fcdSqs return; 42143dec9fcdSqs } 42153dec9fcdSqs 42163dec9fcdSqs MUTEX_ENTER(&hxge_common_lock); 42173dec9fcdSqs h_hw_p = hxge_hw_list; 42183dec9fcdSqs for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 42193dec9fcdSqs p_dip = hw_p->parent_devp; 42203dec9fcdSqs if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip && 42213dec9fcdSqs hxgep->hxge_hw_p->magic == HXGE_MAGIC && 42223dec9fcdSqs hw_p->magic == HXGE_MAGIC) { 42233dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42243dec9fcdSqs "==> hxge_uninit_common_dev: " 42253dec9fcdSqs "hw_p $%p parent dip $%p ndevs %d (found)", 42263dec9fcdSqs hw_p, p_dip, hw_p->ndevs)); 42273dec9fcdSqs 42283dec9fcdSqs hxgep->hxge_hw_p = NULL; 42293dec9fcdSqs if (hw_p->ndevs) { 42303dec9fcdSqs hw_p->ndevs--; 42313dec9fcdSqs } 42323dec9fcdSqs hw_p->hxge_p = NULL; 42333dec9fcdSqs if (!hw_p->ndevs) { 42343dec9fcdSqs MUTEX_DESTROY(&hw_p->hxge_vlan_lock); 42353dec9fcdSqs MUTEX_DESTROY(&hw_p->hxge_tcam_lock); 42363dec9fcdSqs MUTEX_DESTROY(&hw_p->hxge_cfg_lock); 42373dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42383dec9fcdSqs "==> hxge_uninit_common_dev: " 42393dec9fcdSqs "hw_p $%p parent dip $%p ndevs %d (last)", 42403dec9fcdSqs hw_p, p_dip, hw_p->ndevs)); 42413dec9fcdSqs 42423dec9fcdSqs if (hw_p == hxge_hw_list) { 42433dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42443dec9fcdSqs "==> hxge_uninit_common_dev:" 42453dec9fcdSqs "remove head " 42463dec9fcdSqs "hw_p $%p parent dip $%p " 42473dec9fcdSqs "ndevs %d (head)", 42483dec9fcdSqs hw_p, p_dip, hw_p->ndevs)); 42493dec9fcdSqs hxge_hw_list = hw_p->next; 42503dec9fcdSqs } else { 42513dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42523dec9fcdSqs "==> hxge_uninit_common_dev:" 42533dec9fcdSqs "remove middle " 42543dec9fcdSqs "hw_p $%p parent dip $%p " 42553dec9fcdSqs "ndevs %d (middle)", 42563dec9fcdSqs hw_p, p_dip, hw_p->ndevs)); 42573dec9fcdSqs h_hw_p->next = hw_p->next; 42583dec9fcdSqs } 42593dec9fcdSqs 42603dec9fcdSqs KMEM_FREE(hw_p, sizeof (hxge_hw_list_t)); 42613dec9fcdSqs } 42623dec9fcdSqs break; 42633dec9fcdSqs } else { 42643dec9fcdSqs h_hw_p = hw_p; 42653dec9fcdSqs } 42663dec9fcdSqs } 42673dec9fcdSqs 42683dec9fcdSqs MUTEX_EXIT(&hxge_common_lock); 42693dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, 42703dec9fcdSqs "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 42713dec9fcdSqs 42723dec9fcdSqs HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev")); 42733dec9fcdSqs } 4274*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4275*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static void 4276*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_link_poll(void *arg) 4277*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States { 4278*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_t hxgep = (p_hxge_t)arg; 4279*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hpi_handle_t handle; 4280*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_stats_t statsp; 4281*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States cip_link_stat_t link_stat; 4282*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_timeout *to = &hxgep->timeout; 4283*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4284*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States handle = HXGE_DEV_HPI_HANDLE(hxgep); 4285*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp = (p_hxge_stats_t)hxgep->statsp; 4286*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value); 4287*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4288*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (to->link_status != link_stat.bits.xpcs0_link_up) { 4289*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States to->link_status = link_stat.bits.xpcs0_link_up; 4290*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4291*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (link_stat.bits.xpcs0_link_up) { 4292*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mac_link_update(hxgep->mach, LINK_STATE_UP); 4293*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_speed = 10000; 4294*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_duplex = 2; 4295*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_up = 1; 4296*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 4297*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mac_link_update(hxgep->mach, LINK_STATE_DOWN); 4298*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_speed = 0; 4299*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_duplex = 0; 4300*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States statsp->mac_stats.link_up = 0; 4301*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 4302*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 4303*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 4304*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* Restart the link status timer to check the link status */ 4305*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&to->lock); 4306*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States to->id = timeout(hxge_link_poll, arg, to->ticks); 4307*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&to->lock); 4308*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 4309