16349Sqs148142 /*
26349Sqs148142 * CDDL HEADER START
36349Sqs148142 *
46349Sqs148142 * The contents of this file are subject to the terms of the
56349Sqs148142 * Common Development and Distribution License (the "License").
66349Sqs148142 * You may not use this file except in compliance with the License.
76349Sqs148142 *
86349Sqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96349Sqs148142 * or http://www.opensolaris.org/os/licensing.
106349Sqs148142 * See the License for the specific language governing permissions
116349Sqs148142 * and limitations under the License.
126349Sqs148142 *
136349Sqs148142 * When distributing Covered Code, include this CDDL HEADER in each
146349Sqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156349Sqs148142 * If applicable, add the following below this CDDL HEADER, with the
166349Sqs148142 * fields enclosed by brackets "[]" replaced with your own identifying
176349Sqs148142 * information: Portions Copyright [yyyy] [name of copyright owner]
186349Sqs148142 *
196349Sqs148142 * CDDL HEADER END
206349Sqs148142 */
216349Sqs148142 /*
22*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
236349Sqs148142 * Use is subject to license terms.
246349Sqs148142 */
256349Sqs148142
266349Sqs148142 /*
276349Sqs148142 * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver.
286349Sqs148142 */
296349Sqs148142 #include <hxge_impl.h>
306349Sqs148142 #include <hxge_pfc.h>
316349Sqs148142
326349Sqs148142 /*
336349Sqs148142 * PSARC/2007/453 MSI-X interrupt limit override
346349Sqs148142 * (This PSARC case is limited to MSI-X vectors
356349Sqs148142 * and SPARC platforms only).
366349Sqs148142 */
376349Sqs148142 uint32_t hxge_msi_enable = 2;
386349Sqs148142
396349Sqs148142 /*
406349Sqs148142 * Globals: tunable parameters (/etc/system or adb)
416349Sqs148142 *
426349Sqs148142 */
436349Sqs148142 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT;
446349Sqs148142 uint32_t hxge_rbr_spare_size = 0;
456349Sqs148142 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT;
466349Sqs148142 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT;
476349Sqs148142 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX;
486349Sqs148142 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN;
496349Sqs148142 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN;
507584SQiyan.Sun@Sun.COM uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE;
516349Sqs148142
526349Sqs148142 static hxge_os_mutex_t hxgedebuglock;
536349Sqs148142 static int hxge_debug_init = 0;
546349Sqs148142
556349Sqs148142 /*
566349Sqs148142 * Debugging flags:
576349Sqs148142 * hxge_no_tx_lb : transmit load balancing
586349Sqs148142 * hxge_tx_lb_policy: 0 - TCP/UDP port (default)
596349Sqs148142 * 1 - From the Stack
606349Sqs148142 * 2 - Destination IP Address
616349Sqs148142 */
626349Sqs148142 uint32_t hxge_no_tx_lb = 0;
636349Sqs148142 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP;
646349Sqs148142
656349Sqs148142 /*
666349Sqs148142 * Tunables to manage the receive buffer blocks.
676349Sqs148142 *
686349Sqs148142 * hxge_rx_threshold_hi: copy all buffers.
696349Sqs148142 * hxge_rx_bcopy_size_type: receive buffer block size type.
706349Sqs148142 * hxge_rx_threshold_lo: copy only up to tunable block size type.
716349Sqs148142 */
7211257SMichael.Speer@Sun.COM #if defined(__sparc)
7311257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6;
7411257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_4;
7511257SMichael.Speer@Sun.COM #else
768366SQiyan.Sun@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_NONE;
7711257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_NONE;
7811257SMichael.Speer@Sun.COM #endif
796349Sqs148142 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
806349Sqs148142
816349Sqs148142 rtrace_t hpi_rtracebuf;
826349Sqs148142
836349Sqs148142 /*
846349Sqs148142 * Function Prototypes
856349Sqs148142 */
866349Sqs148142 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t);
876349Sqs148142 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t);
886349Sqs148142 static void hxge_unattach(p_hxge_t);
896349Sqs148142
906349Sqs148142 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t);
916349Sqs148142
926349Sqs148142 static hxge_status_t hxge_setup_mutexes(p_hxge_t);
936349Sqs148142 static void hxge_destroy_mutexes(p_hxge_t);
946349Sqs148142
956349Sqs148142 static hxge_status_t hxge_map_regs(p_hxge_t hxgep);
966349Sqs148142 static void hxge_unmap_regs(p_hxge_t hxgep);
976349Sqs148142
9811257SMichael.Speer@Sun.COM static hxge_status_t hxge_add_intrs(p_hxge_t hxgep);
996349Sqs148142 static void hxge_remove_intrs(p_hxge_t hxgep);
1006349Sqs148142 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep);
1016349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t);
1026349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t);
10311257SMichael.Speer@Sun.COM static void hxge_intrs_enable(p_hxge_t hxgep);
1046349Sqs148142 static void hxge_intrs_disable(p_hxge_t hxgep);
1056349Sqs148142 static void hxge_suspend(p_hxge_t);
1066349Sqs148142 static hxge_status_t hxge_resume(p_hxge_t);
10711257SMichael.Speer@Sun.COM static hxge_status_t hxge_setup_dev(p_hxge_t);
1086349Sqs148142 static void hxge_destroy_dev(p_hxge_t);
10911257SMichael.Speer@Sun.COM static hxge_status_t hxge_alloc_mem_pool(p_hxge_t);
1106349Sqs148142 static void hxge_free_mem_pool(p_hxge_t);
1116349Sqs148142 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t);
1126349Sqs148142 static void hxge_free_rx_mem_pool(p_hxge_t);
1136349Sqs148142 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t);
1146349Sqs148142 static void hxge_free_tx_mem_pool(p_hxge_t);
1156349Sqs148142 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t,
1166349Sqs148142 struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t,
1176349Sqs148142 p_hxge_dma_common_t);
1186349Sqs148142 static void hxge_dma_mem_free(p_hxge_dma_common_t);
1196349Sqs148142 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t,
1206349Sqs148142 p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1216349Sqs148142 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1226349Sqs148142 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t,
1237618SMichael.Speer@Sun.COM p_hxge_dma_common_t *, struct ddi_dma_attr *, size_t);
1246349Sqs148142 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1256349Sqs148142 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t,
1266349Sqs148142 p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1276349Sqs148142 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1286349Sqs148142 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t,
1296349Sqs148142 p_hxge_dma_common_t *, size_t);
1306349Sqs148142 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1316349Sqs148142 static int hxge_init_common_dev(p_hxge_t);
1326349Sqs148142 static void hxge_uninit_common_dev(p_hxge_t);
1336349Sqs148142
1346349Sqs148142 /*
1356349Sqs148142 * The next declarations are for the GLDv3 interface.
1366349Sqs148142 */
1376349Sqs148142 static int hxge_m_start(void *);
1386349Sqs148142 static void hxge_m_stop(void *);
1396349Sqs148142 static int hxge_m_multicst(void *, boolean_t, const uint8_t *);
1406349Sqs148142 static int hxge_m_promisc(void *, boolean_t);
1416349Sqs148142 static void hxge_m_ioctl(void *, queue_t *, mblk_t *);
1426349Sqs148142 static hxge_status_t hxge_mac_register(p_hxge_t hxgep);
1436349Sqs148142
1446349Sqs148142 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *);
1457584SQiyan.Sun@Sun.COM static boolean_t hxge_param_locked(mac_prop_id_t pr_num);
1467584SQiyan.Sun@Sun.COM static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
1477584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val);
1487584SQiyan.Sun@Sun.COM static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
1497584SQiyan.Sun@Sun.COM uint_t pr_valsize, void *pr_val);
150*11878SVenu.Iyer@Sun.COM static void hxge_m_propinfo(void *barg, const char *pr_name,
151*11878SVenu.Iyer@Sun.COM mac_prop_id_t pr_num, mac_prop_info_handle_t mph);
1527584SQiyan.Sun@Sun.COM static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name,
1537584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val);
1547584SQiyan.Sun@Sun.COM static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name,
155*11878SVenu.Iyer@Sun.COM uint_t pr_valsize, void *pr_val);
1567584SQiyan.Sun@Sun.COM static void hxge_link_poll(void *arg);
1577949SQiyan.Sun@Sun.COM static void hxge_link_update(p_hxge_t hxge, link_state_t state);
1588236SQiyan.Sun@Sun.COM static void hxge_msix_init(p_hxge_t hxgep);
1597584SQiyan.Sun@Sun.COM
160*11878SVenu.Iyer@Sun.COM char *hxge_priv_props[] = {
161*11878SVenu.Iyer@Sun.COM "_rxdma_intr_time",
162*11878SVenu.Iyer@Sun.COM "_rxdma_intr_pkts",
163*11878SVenu.Iyer@Sun.COM "_class_opt_ipv4_tcp",
164*11878SVenu.Iyer@Sun.COM "_class_opt_ipv4_udp",
165*11878SVenu.Iyer@Sun.COM "_class_opt_ipv4_ah",
166*11878SVenu.Iyer@Sun.COM "_class_opt_ipv4_sctp",
167*11878SVenu.Iyer@Sun.COM "_class_opt_ipv6_tcp",
168*11878SVenu.Iyer@Sun.COM "_class_opt_ipv6_udp",
169*11878SVenu.Iyer@Sun.COM "_class_opt_ipv6_ah",
170*11878SVenu.Iyer@Sun.COM "_class_opt_ipv6_sctp",
171*11878SVenu.Iyer@Sun.COM NULL
1727584SQiyan.Sun@Sun.COM };
1737584SQiyan.Sun@Sun.COM
1747584SQiyan.Sun@Sun.COM #define HXGE_MAX_PRIV_PROPS \
1757584SQiyan.Sun@Sun.COM (sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t))
1766349Sqs148142
1776349Sqs148142 #define HXGE_MAGIC 0x4E584745UL
1786349Sqs148142 #define MAX_DUMP_SZ 256
1796349Sqs148142
1807584SQiyan.Sun@Sun.COM #define HXGE_M_CALLBACK_FLAGS \
181*11878SVenu.Iyer@Sun.COM (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1826349Sqs148142
1836349Sqs148142 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep);
1846349Sqs148142
1856349Sqs148142 static mac_callbacks_t hxge_m_callbacks = {
1866349Sqs148142 HXGE_M_CALLBACK_FLAGS,
1876349Sqs148142 hxge_m_stat,
1886349Sqs148142 hxge_m_start,
1896349Sqs148142 hxge_m_stop,
1906349Sqs148142 hxge_m_promisc,
1916349Sqs148142 hxge_m_multicst,
1928718SMichael.Speer@Sun.COM NULL,
1938718SMichael.Speer@Sun.COM NULL,
194*11878SVenu.Iyer@Sun.COM NULL,
1956349Sqs148142 hxge_m_ioctl,
1967584SQiyan.Sun@Sun.COM hxge_m_getcapab,
1977584SQiyan.Sun@Sun.COM NULL,
1987584SQiyan.Sun@Sun.COM NULL,
1997584SQiyan.Sun@Sun.COM hxge_m_setprop,
200*11878SVenu.Iyer@Sun.COM hxge_m_getprop,
201*11878SVenu.Iyer@Sun.COM hxge_m_propinfo
2026349Sqs148142 };
2036349Sqs148142
2048366SQiyan.Sun@Sun.COM /* PSARC/2007/453 MSI-X interrupt limit override. */
2058366SQiyan.Sun@Sun.COM #define HXGE_MSIX_REQUEST_10G 8
2068366SQiyan.Sun@Sun.COM static int hxge_create_msi_property(p_hxge_t);
2078366SQiyan.Sun@Sun.COM
2086349Sqs148142 /* Enable debug messages as necessary. */
2097584SQiyan.Sun@Sun.COM uint64_t hxge_debug_level = 0;
2106349Sqs148142
2116349Sqs148142 /*
2126349Sqs148142 * This list contains the instance structures for the Hydra
2136349Sqs148142 * devices present in the system. The lock exists to guarantee
2146349Sqs148142 * mutually exclusive access to the list.
2156349Sqs148142 */
2166349Sqs148142 void *hxge_list = NULL;
2176349Sqs148142 void *hxge_hw_list = NULL;
2186349Sqs148142 hxge_os_mutex_t hxge_common_lock;
2196349Sqs148142
2206349Sqs148142 extern uint64_t hpi_debug_level;
2216349Sqs148142
2226349Sqs148142 extern hxge_status_t hxge_ldgv_init();
2236349Sqs148142 extern hxge_status_t hxge_ldgv_uninit();
2246349Sqs148142 extern hxge_status_t hxge_intr_ldgv_init();
2256349Sqs148142 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
22611257SMichael.Speer@Sun.COM ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr);
2276349Sqs148142 extern void hxge_fm_fini(p_hxge_t hxgep);
2286349Sqs148142
2296349Sqs148142 /*
2306349Sqs148142 * Count used to maintain the number of buffers being used
2316349Sqs148142 * by Hydra instances and loaned up to the upper layers.
2326349Sqs148142 */
2336349Sqs148142 uint32_t hxge_mblks_pending = 0;
2346349Sqs148142
2356349Sqs148142 /*
2366349Sqs148142 * Device register access attributes for PIO.
2376349Sqs148142 */
2386349Sqs148142 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = {
23911257SMichael.Speer@Sun.COM DDI_DEVICE_ATTR_V0,
2406349Sqs148142 DDI_STRUCTURE_LE_ACC,
2416349Sqs148142 DDI_STRICTORDER_ACC,
2426349Sqs148142 };
2436349Sqs148142
2446349Sqs148142 /*
2456349Sqs148142 * Device descriptor access attributes for DMA.
2466349Sqs148142 */
2476349Sqs148142 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = {
2486349Sqs148142 DDI_DEVICE_ATTR_V0,
2496349Sqs148142 DDI_STRUCTURE_LE_ACC,
2506349Sqs148142 DDI_STRICTORDER_ACC
2516349Sqs148142 };
2526349Sqs148142
2536349Sqs148142 /*
2546349Sqs148142 * Device buffer access attributes for DMA.
2556349Sqs148142 */
2566349Sqs148142 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = {
2576349Sqs148142 DDI_DEVICE_ATTR_V0,
2586349Sqs148142 DDI_STRUCTURE_BE_ACC,
2596349Sqs148142 DDI_STRICTORDER_ACC
2606349Sqs148142 };
2616349Sqs148142
2627618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rcr_desc_dma_attr = {
2637618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */
2647618SMichael.Speer@Sun.COM 0, /* low address */
2657618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */
2667618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */
2677618SMichael.Speer@Sun.COM 0x80000, /* alignment */
2687618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */
2697618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */
2707618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */
2717618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */
2727618SMichael.Speer@Sun.COM 1, /* scatter/gather list length */
2737618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */
2747618SMichael.Speer@Sun.COM 0 /* attribute flags */
2757618SMichael.Speer@Sun.COM };
2767618SMichael.Speer@Sun.COM
2777618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_tx_desc_dma_attr = {
2786349Sqs148142 DMA_ATTR_V0, /* version number. */
2796349Sqs148142 0, /* low address */
2806349Sqs148142 0xffffffffffffffff, /* high address */
2816349Sqs148142 0xffffffffffffffff, /* address counter max */
2826349Sqs148142 0x100000, /* alignment */
2836349Sqs148142 0xfc00fc, /* dlim_burstsizes */
2846349Sqs148142 0x1, /* minimum transfer size */
2856349Sqs148142 0xffffffffffffffff, /* maximum transfer size */
2866349Sqs148142 0xffffffffffffffff, /* maximum segment size */
2876349Sqs148142 1, /* scatter/gather list length */
2886349Sqs148142 (unsigned int)1, /* granularity */
2896349Sqs148142 0 /* attribute flags */
2906349Sqs148142 };
2916349Sqs148142
2927618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rbr_desc_dma_attr = {
2937618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */
2947618SMichael.Speer@Sun.COM 0, /* low address */
2957618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */
2967618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */
2977618SMichael.Speer@Sun.COM 0x40000, /* alignment */
2987618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */
2997618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */
3007618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */
3017618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */
3027618SMichael.Speer@Sun.COM 1, /* scatter/gather list length */
3037618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */
3047618SMichael.Speer@Sun.COM 0 /* attribute flags */
3057618SMichael.Speer@Sun.COM };
3067618SMichael.Speer@Sun.COM
3077618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_mbox_dma_attr = {
3087618SMichael.Speer@Sun.COM DMA_ATTR_V0, /* version number. */
3097618SMichael.Speer@Sun.COM 0, /* low address */
3107618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* high address */
3117618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* address counter max */
3127618SMichael.Speer@Sun.COM #if defined(_BIG_ENDIAN)
3137618SMichael.Speer@Sun.COM 0x2000, /* alignment */
3147618SMichael.Speer@Sun.COM #else
3157618SMichael.Speer@Sun.COM 0x1000, /* alignment */
3167618SMichael.Speer@Sun.COM #endif
3177618SMichael.Speer@Sun.COM 0xfc00fc, /* dlim_burstsizes */
3187618SMichael.Speer@Sun.COM 0x1, /* minimum transfer size */
3197618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum transfer size */
3207618SMichael.Speer@Sun.COM 0xffffffffffffffff, /* maximum segment size */
3217618SMichael.Speer@Sun.COM 5, /* scatter/gather list length */
3227618SMichael.Speer@Sun.COM (unsigned int)1, /* granularity */
3237618SMichael.Speer@Sun.COM 0 /* attribute flags */
3247618SMichael.Speer@Sun.COM };
3257618SMichael.Speer@Sun.COM
3266349Sqs148142 ddi_dma_attr_t hxge_tx_dma_attr = {
3276349Sqs148142 DMA_ATTR_V0, /* version number. */
3286349Sqs148142 0, /* low address */
3296349Sqs148142 0xffffffffffffffff, /* high address */
3306349Sqs148142 0xffffffffffffffff, /* address counter max */
3316349Sqs148142 #if defined(_BIG_ENDIAN)
3326349Sqs148142 0x2000, /* alignment */
3336349Sqs148142 #else
3346349Sqs148142 0x1000, /* alignment */
3356349Sqs148142 #endif
3366349Sqs148142 0xfc00fc, /* dlim_burstsizes */
3376349Sqs148142 0x1, /* minimum transfer size */
3386349Sqs148142 0xffffffffffffffff, /* maximum transfer size */
3396349Sqs148142 0xffffffffffffffff, /* maximum segment size */
3406349Sqs148142 5, /* scatter/gather list length */
3416349Sqs148142 (unsigned int)1, /* granularity */
3426349Sqs148142 0 /* attribute flags */
3436349Sqs148142 };
3446349Sqs148142
3456349Sqs148142 ddi_dma_attr_t hxge_rx_dma_attr = {
3466349Sqs148142 DMA_ATTR_V0, /* version number. */
3476349Sqs148142 0, /* low address */
3486349Sqs148142 0xffffffffffffffff, /* high address */
3496349Sqs148142 0xffffffffffffffff, /* address counter max */
3506349Sqs148142 0x10000, /* alignment */
3516349Sqs148142 0xfc00fc, /* dlim_burstsizes */
3526349Sqs148142 0x1, /* minimum transfer size */
3536349Sqs148142 0xffffffffffffffff, /* maximum transfer size */
3546349Sqs148142 0xffffffffffffffff, /* maximum segment size */
3556349Sqs148142 1, /* scatter/gather list length */
3566349Sqs148142 (unsigned int)1, /* granularity */
3576349Sqs148142 DDI_DMA_RELAXED_ORDERING /* attribute flags */
3586349Sqs148142 };
3596349Sqs148142
3606349Sqs148142 ddi_dma_lim_t hxge_dma_limits = {
3616349Sqs148142 (uint_t)0, /* dlim_addr_lo */
3626349Sqs148142 (uint_t)0xffffffff, /* dlim_addr_hi */
3636349Sqs148142 (uint_t)0xffffffff, /* dlim_cntr_max */
3646349Sqs148142 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */
3656349Sqs148142 0x1, /* dlim_minxfer */
3666349Sqs148142 1024 /* dlim_speed */
3676349Sqs148142 };
3686349Sqs148142
3696349Sqs148142 dma_method_t hxge_force_dma = DVMA;
3706349Sqs148142
3716349Sqs148142 /*
3726349Sqs148142 * dma chunk sizes.
3736349Sqs148142 *
3746349Sqs148142 * Try to allocate the largest possible size
3756349Sqs148142 * so that fewer number of dma chunks would be managed
3766349Sqs148142 */
3776349Sqs148142 size_t alloc_sizes[] = {
3786349Sqs148142 0x1000, 0x2000, 0x4000, 0x8000,
3796349Sqs148142 0x10000, 0x20000, 0x40000, 0x80000,
3806349Sqs148142 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000
3816349Sqs148142 };
3826349Sqs148142
3836349Sqs148142 /*
3846349Sqs148142 * Translate "dev_t" to a pointer to the associated "dev_info_t".
3856349Sqs148142 */
3866349Sqs148142 static int
hxge_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)3876349Sqs148142 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3886349Sqs148142 {
3896349Sqs148142 p_hxge_t hxgep = NULL;
3906349Sqs148142 int instance;
3916349Sqs148142 int status = DDI_SUCCESS;
3928718SMichael.Speer@Sun.COM int i;
3936349Sqs148142
3946349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach"));
3956349Sqs148142
3966349Sqs148142 /*
3976349Sqs148142 * Get the device instance since we'll need to setup or retrieve a soft
3986349Sqs148142 * state for this instance.
3996349Sqs148142 */
4006349Sqs148142 instance = ddi_get_instance(dip);
4016349Sqs148142
4026349Sqs148142 switch (cmd) {
4036349Sqs148142 case DDI_ATTACH:
4046349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH"));
4056349Sqs148142 break;
4066349Sqs148142
4076349Sqs148142 case DDI_RESUME:
4086349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME"));
4096349Sqs148142 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
4106349Sqs148142 if (hxgep == NULL) {
4116349Sqs148142 status = DDI_FAILURE;
4126349Sqs148142 break;
4136349Sqs148142 }
4146349Sqs148142 if (hxgep->dip != dip) {
4156349Sqs148142 status = DDI_FAILURE;
4166349Sqs148142 break;
4176349Sqs148142 }
4186349Sqs148142 if (hxgep->suspended == DDI_PM_SUSPEND) {
4196349Sqs148142 status = ddi_dev_is_needed(hxgep->dip, 0, 1);
4206349Sqs148142 } else {
4216349Sqs148142 (void) hxge_resume(hxgep);
4226349Sqs148142 }
4236349Sqs148142 goto hxge_attach_exit;
4246349Sqs148142
4256349Sqs148142 case DDI_PM_RESUME:
4266349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME"));
4276349Sqs148142 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
4286349Sqs148142 if (hxgep == NULL) {
4296349Sqs148142 status = DDI_FAILURE;
4306349Sqs148142 break;
4316349Sqs148142 }
4326349Sqs148142 if (hxgep->dip != dip) {
4336349Sqs148142 status = DDI_FAILURE;
4346349Sqs148142 break;
4356349Sqs148142 }
4366349Sqs148142 (void) hxge_resume(hxgep);
4376349Sqs148142 goto hxge_attach_exit;
4386349Sqs148142
4396349Sqs148142 default:
4406349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown"));
4416349Sqs148142 status = DDI_FAILURE;
4426349Sqs148142 goto hxge_attach_exit;
4436349Sqs148142 }
4446349Sqs148142
4456349Sqs148142 if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) {
4466349Sqs148142 status = DDI_FAILURE;
4476349Sqs148142 HXGE_ERROR_MSG((hxgep, DDI_CTL,
4486349Sqs148142 "ddi_soft_state_zalloc failed"));
4496349Sqs148142 goto hxge_attach_exit;
4506349Sqs148142 }
4516349Sqs148142
4526349Sqs148142 hxgep = ddi_get_soft_state(hxge_list, instance);
4536349Sqs148142 if (hxgep == NULL) {
4546349Sqs148142 status = HXGE_ERROR;
4556349Sqs148142 HXGE_ERROR_MSG((hxgep, DDI_CTL,
4566349Sqs148142 "ddi_get_soft_state failed"));
4576349Sqs148142 goto hxge_attach_fail2;
4586349Sqs148142 }
4596349Sqs148142
4606349Sqs148142 hxgep->drv_state = 0;
4616349Sqs148142 hxgep->dip = dip;
4626349Sqs148142 hxgep->instance = instance;
4636349Sqs148142 hxgep->p_dip = ddi_get_parent(dip);
4646349Sqs148142 hxgep->hxge_debug_level = hxge_debug_level;
4656349Sqs148142 hpi_debug_level = hxge_debug_level;
4666349Sqs148142
4678718SMichael.Speer@Sun.COM /*
4688718SMichael.Speer@Sun.COM * Initialize MMAC struture.
4698718SMichael.Speer@Sun.COM */
4708718SMichael.Speer@Sun.COM (void) hxge_pfc_num_macs_get(hxgep, &hxgep->mmac.total);
4718718SMichael.Speer@Sun.COM hxgep->mmac.available = hxgep->mmac.total;
4728718SMichael.Speer@Sun.COM for (i = 0; i < hxgep->mmac.total; i++) {
4738718SMichael.Speer@Sun.COM hxgep->mmac.addrs[i].set = B_FALSE;
4748718SMichael.Speer@Sun.COM hxgep->mmac.addrs[i].primary = B_FALSE;
4758718SMichael.Speer@Sun.COM }
4768718SMichael.Speer@Sun.COM
47711257SMichael.Speer@Sun.COM hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr,
47811257SMichael.Speer@Sun.COM &hxge_rx_dma_attr);
4796349Sqs148142
4806349Sqs148142 status = hxge_map_regs(hxgep);
4816349Sqs148142 if (status != HXGE_OK) {
4826349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed"));
4836349Sqs148142 goto hxge_attach_fail3;
4846349Sqs148142 }
4856349Sqs148142
4866349Sqs148142 status = hxge_init_common_dev(hxgep);
4876349Sqs148142 if (status != HXGE_OK) {
4886349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4896349Sqs148142 "hxge_init_common_dev failed"));
4906349Sqs148142 goto hxge_attach_fail4;
4916349Sqs148142 }
4926349Sqs148142
4936349Sqs148142 /*
4946349Sqs148142 * Setup the Ndd parameters for this instance.
4956349Sqs148142 */
4966349Sqs148142 hxge_init_param(hxgep);
4976349Sqs148142
4986349Sqs148142 /*
4996349Sqs148142 * Setup Register Tracing Buffer.
5006349Sqs148142 */
5016349Sqs148142 hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf);
5026349Sqs148142
5036349Sqs148142 /* init stats ptr */
5046349Sqs148142 hxge_init_statsp(hxgep);
5056349Sqs148142
5067584SQiyan.Sun@Sun.COM status = hxge_setup_mutexes(hxgep);
5077584SQiyan.Sun@Sun.COM if (status != HXGE_OK) {
5087584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed"));
5097584SQiyan.Sun@Sun.COM goto hxge_attach_fail;
5107584SQiyan.Sun@Sun.COM }
5117584SQiyan.Sun@Sun.COM
5128791SMichael.Speer@Sun.COM /* Scrub the MSI-X memory */
5138791SMichael.Speer@Sun.COM hxge_msix_init(hxgep);
5148791SMichael.Speer@Sun.COM
5156349Sqs148142 status = hxge_get_config_properties(hxgep);
5166349Sqs148142 if (status != HXGE_OK) {
5176349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed"));
5186349Sqs148142 goto hxge_attach_fail;
5196349Sqs148142 }
5206349Sqs148142
5216349Sqs148142 /*
5226349Sqs148142 * Setup the Kstats for the driver.
5236349Sqs148142 */
5246349Sqs148142 hxge_setup_kstats(hxgep);
5256349Sqs148142 hxge_setup_param(hxgep);
5266349Sqs148142
5276349Sqs148142 status = hxge_setup_system_dma_pages(hxgep);
5286349Sqs148142 if (status != HXGE_OK) {
5296349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed"));
5306349Sqs148142 goto hxge_attach_fail;
5316349Sqs148142 }
5326349Sqs148142
5336349Sqs148142 hxge_hw_id_init(hxgep);
5346349Sqs148142 hxge_hw_init_niu_common(hxgep);
5356349Sqs148142
5366349Sqs148142 status = hxge_setup_dev(hxgep);
5376349Sqs148142 if (status != DDI_SUCCESS) {
5386349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed"));
5396349Sqs148142 goto hxge_attach_fail;
5406349Sqs148142 }
5416349Sqs148142
5426349Sqs148142 status = hxge_add_intrs(hxgep);
5436349Sqs148142 if (status != DDI_SUCCESS) {
5446349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed"));
5456349Sqs148142 goto hxge_attach_fail;
5466349Sqs148142 }
5476349Sqs148142
5486349Sqs148142 /*
5496349Sqs148142 * Enable interrupts.
5506349Sqs148142 */
5516349Sqs148142 hxge_intrs_enable(hxgep);
5526349Sqs148142
5536349Sqs148142 if ((status = hxge_mac_register(hxgep)) != HXGE_OK) {
5546349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
5556349Sqs148142 "unable to register to mac layer (%d)", status));
5566349Sqs148142 goto hxge_attach_fail;
5576349Sqs148142 }
5587584SQiyan.Sun@Sun.COM mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN);
5596349Sqs148142
5606349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)",
5616349Sqs148142 instance));
5626349Sqs148142
5636349Sqs148142 goto hxge_attach_exit;
5646349Sqs148142
5656349Sqs148142 hxge_attach_fail:
5666349Sqs148142 hxge_unattach(hxgep);
5676349Sqs148142 goto hxge_attach_fail1;
5686349Sqs148142
5696349Sqs148142 hxge_attach_fail5:
5706349Sqs148142 /*
5716349Sqs148142 * Tear down the ndd parameters setup.
5726349Sqs148142 */
5736349Sqs148142 hxge_destroy_param(hxgep);
5746349Sqs148142
5756349Sqs148142 /*
5766349Sqs148142 * Tear down the kstat setup.
5776349Sqs148142 */
5786349Sqs148142 hxge_destroy_kstats(hxgep);
5796349Sqs148142
5806349Sqs148142 hxge_attach_fail4:
5816349Sqs148142 if (hxgep->hxge_hw_p) {
5826349Sqs148142 hxge_uninit_common_dev(hxgep);
5836349Sqs148142 hxgep->hxge_hw_p = NULL;
5846349Sqs148142 }
5856349Sqs148142 hxge_attach_fail3:
5866349Sqs148142 /*
5876349Sqs148142 * Unmap the register setup.
5886349Sqs148142 */
5896349Sqs148142 hxge_unmap_regs(hxgep);
5906349Sqs148142
5916349Sqs148142 hxge_fm_fini(hxgep);
5926349Sqs148142
5936349Sqs148142 hxge_attach_fail2:
5946349Sqs148142 ddi_soft_state_free(hxge_list, hxgep->instance);
5956349Sqs148142
5966349Sqs148142 hxge_attach_fail1:
5976349Sqs148142 if (status != HXGE_OK)
5986349Sqs148142 status = (HXGE_ERROR | HXGE_DDI_FAILED);
5996349Sqs148142 hxgep = NULL;
6006349Sqs148142
6016349Sqs148142 hxge_attach_exit:
6026349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x",
6036349Sqs148142 status));
6046349Sqs148142
6056349Sqs148142 return (status);
6066349Sqs148142 }
6076349Sqs148142
6086349Sqs148142 static int
hxge_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)6096349Sqs148142 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
6106349Sqs148142 {
6116349Sqs148142 int status = DDI_SUCCESS;
6126349Sqs148142 int instance;
6136349Sqs148142 p_hxge_t hxgep = NULL;
6146349Sqs148142
6156349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach"));
6166349Sqs148142 instance = ddi_get_instance(dip);
6176349Sqs148142 hxgep = ddi_get_soft_state(hxge_list, instance);
6186349Sqs148142 if (hxgep == NULL) {
6196349Sqs148142 status = DDI_FAILURE;
6206349Sqs148142 goto hxge_detach_exit;
6216349Sqs148142 }
6226349Sqs148142
6236349Sqs148142 switch (cmd) {
6246349Sqs148142 case DDI_DETACH:
6256349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH"));
6266349Sqs148142 break;
6276349Sqs148142
6286349Sqs148142 case DDI_PM_SUSPEND:
6296349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
6306349Sqs148142 hxgep->suspended = DDI_PM_SUSPEND;
6316349Sqs148142 hxge_suspend(hxgep);
6326349Sqs148142 break;
6336349Sqs148142
6346349Sqs148142 case DDI_SUSPEND:
6356349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND"));
6366349Sqs148142 if (hxgep->suspended != DDI_PM_SUSPEND) {
6376349Sqs148142 hxgep->suspended = DDI_SUSPEND;
6386349Sqs148142 hxge_suspend(hxgep);
6396349Sqs148142 }
6406349Sqs148142 break;
6416349Sqs148142
6426349Sqs148142 default:
6436349Sqs148142 status = DDI_FAILURE;
6446349Sqs148142 break;
6456349Sqs148142 }
6466349Sqs148142
6476349Sqs148142 if (cmd != DDI_DETACH)
6486349Sqs148142 goto hxge_detach_exit;
6496349Sqs148142
6506349Sqs148142 /*
6516349Sqs148142 * Stop the xcvr polling.
6526349Sqs148142 */
6536349Sqs148142 hxgep->suspended = cmd;
6546349Sqs148142
6556349Sqs148142 if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) {
6566349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6576349Sqs148142 "<== hxge_detach status = 0x%08X", status));
6586349Sqs148142 return (DDI_FAILURE);
6596349Sqs148142 }
6606349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
6616349Sqs148142 "<== hxge_detach (mac_unregister) status = 0x%08X", status));
6626349Sqs148142
6636349Sqs148142 hxge_unattach(hxgep);
6646349Sqs148142 hxgep = NULL;
6656349Sqs148142
6666349Sqs148142 hxge_detach_exit:
6676349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X",
6686349Sqs148142 status));
6696349Sqs148142
6706349Sqs148142 return (status);
6716349Sqs148142 }
6726349Sqs148142
6736349Sqs148142 static void
hxge_unattach(p_hxge_t hxgep)6746349Sqs148142 hxge_unattach(p_hxge_t hxgep)
6756349Sqs148142 {
6766349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach"));
6776349Sqs148142
6786349Sqs148142 if (hxgep == NULL || hxgep->dev_regs == NULL) {
6796349Sqs148142 return;
6806349Sqs148142 }
6816349Sqs148142
6826349Sqs148142 if (hxgep->hxge_hw_p) {
6836349Sqs148142 hxge_uninit_common_dev(hxgep);
6846349Sqs148142 hxgep->hxge_hw_p = NULL;
6856349Sqs148142 }
6866349Sqs148142
6876349Sqs148142 if (hxgep->hxge_timerid) {
6886349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid);
6896349Sqs148142 hxgep->hxge_timerid = 0;
6906349Sqs148142 }
6916349Sqs148142
69211257SMichael.Speer@Sun.COM /* Stop interrupts. */
69311257SMichael.Speer@Sun.COM hxge_intrs_disable(hxgep);
69411257SMichael.Speer@Sun.COM
6956349Sqs148142 /* Stop any further interrupts. */
6966349Sqs148142 hxge_remove_intrs(hxgep);
6976349Sqs148142
6986349Sqs148142 /* Stop the device and free resources. */
6996349Sqs148142 hxge_destroy_dev(hxgep);
7006349Sqs148142
7016349Sqs148142 /* Tear down the ndd parameters setup. */
7026349Sqs148142 hxge_destroy_param(hxgep);
7036349Sqs148142
7046349Sqs148142 /* Tear down the kstat setup. */
7056349Sqs148142 hxge_destroy_kstats(hxgep);
7066349Sqs148142
7076349Sqs148142 /*
7086349Sqs148142 * Remove the list of ndd parameters which were setup during attach.
7096349Sqs148142 */
7106349Sqs148142 if (hxgep->dip) {
7116349Sqs148142 HXGE_DEBUG_MSG((hxgep, OBP_CTL,
7126349Sqs148142 " hxge_unattach: remove all properties"));
7136349Sqs148142 (void) ddi_prop_remove_all(hxgep->dip);
7146349Sqs148142 }
7156349Sqs148142
7166349Sqs148142 /*
7176864Sqs148142 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any
7186864Sqs148142 * previous state before unmapping the registers.
7196864Sqs148142 */
7206864Sqs148142 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E);
7216864Sqs148142 HXGE_DELAY(1000);
7226864Sqs148142
7236864Sqs148142 /*
7246349Sqs148142 * Unmap the register setup.
7256349Sqs148142 */
7266349Sqs148142 hxge_unmap_regs(hxgep);
7276349Sqs148142
7286349Sqs148142 hxge_fm_fini(hxgep);
7296349Sqs148142
7307584SQiyan.Sun@Sun.COM /* Destroy all mutexes. */
7317584SQiyan.Sun@Sun.COM hxge_destroy_mutexes(hxgep);
7327584SQiyan.Sun@Sun.COM
7336349Sqs148142 /*
7346349Sqs148142 * Free the soft state data structures allocated with this instance.
7356349Sqs148142 */
7366349Sqs148142 ddi_soft_state_free(hxge_list, hxgep->instance);
7376349Sqs148142
7386349Sqs148142 HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach"));
7396349Sqs148142 }
7406349Sqs148142
7416349Sqs148142 static hxge_status_t
hxge_map_regs(p_hxge_t hxgep)7426349Sqs148142 hxge_map_regs(p_hxge_t hxgep)
7436349Sqs148142 {
7446349Sqs148142 int ddi_status = DDI_SUCCESS;
7456349Sqs148142 p_dev_regs_t dev_regs;
7466349Sqs148142
7476349Sqs148142 #ifdef HXGE_DEBUG
7486349Sqs148142 char *sysname;
7496349Sqs148142 #endif
7506349Sqs148142
7516349Sqs148142 off_t regsize;
7526349Sqs148142 hxge_status_t status = HXGE_OK;
7536349Sqs148142 int nregs;
7546349Sqs148142
7556349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs"));
7566349Sqs148142
7576349Sqs148142 if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS)
7586349Sqs148142 return (HXGE_ERROR);
7596349Sqs148142
7606349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs));
7616349Sqs148142
7626349Sqs148142 hxgep->dev_regs = NULL;
7636349Sqs148142 dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
7646349Sqs148142 dev_regs->hxge_regh = NULL;
7656349Sqs148142 dev_regs->hxge_pciregh = NULL;
7666349Sqs148142 dev_regs->hxge_msix_regh = NULL;
7676349Sqs148142
7686349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 0, ®size);
7696349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7706349Sqs148142 "hxge_map_regs: pci config size 0x%x", regsize));
7716349Sqs148142
7726349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 0,
7736349Sqs148142 (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0,
7746349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh);
7756349Sqs148142 if (ddi_status != DDI_SUCCESS) {
7766349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7776349Sqs148142 "ddi_map_regs, hxge bus config regs failed"));
7786349Sqs148142 goto hxge_map_regs_fail0;
7796349Sqs148142 }
7806349Sqs148142
7816349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7826349Sqs148142 "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx",
7836349Sqs148142 dev_regs->hxge_pciregp,
7846349Sqs148142 dev_regs->hxge_pciregh));
7856349Sqs148142
7866349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 1, ®size);
7876349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7886349Sqs148142 "hxge_map_regs: pio size 0x%x", regsize));
7896349Sqs148142
7906349Sqs148142 /* set up the device mapped register */
7916349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 1,
7926349Sqs148142 (caddr_t *)&(dev_regs->hxge_regp), 0, 0,
7936349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh);
7946349Sqs148142
7956349Sqs148142 if (ddi_status != DDI_SUCCESS) {
7966349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7976349Sqs148142 "ddi_map_regs for Hydra global reg failed"));
7986349Sqs148142 goto hxge_map_regs_fail1;
7996349Sqs148142 }
8006349Sqs148142
8016349Sqs148142 /* set up the msi/msi-x mapped register */
8026349Sqs148142 (void) ddi_dev_regsize(hxgep->dip, 2, ®size);
8036349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8046349Sqs148142 "hxge_map_regs: msix size 0x%x", regsize));
8056349Sqs148142
8066349Sqs148142 ddi_status = ddi_regs_map_setup(hxgep->dip, 2,
8076349Sqs148142 (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0,
8086349Sqs148142 &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh);
8096349Sqs148142
8106349Sqs148142 if (ddi_status != DDI_SUCCESS) {
8116349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8126349Sqs148142 "ddi_map_regs for msi reg failed"));
8136349Sqs148142 goto hxge_map_regs_fail2;
8146349Sqs148142 }
8156349Sqs148142
8166349Sqs148142 hxgep->dev_regs = dev_regs;
8176349Sqs148142
8186349Sqs148142 HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh);
8196349Sqs148142 HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp);
8206349Sqs148142 HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh);
8216349Sqs148142 HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp);
8226349Sqs148142
8236349Sqs148142 HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
8246349Sqs148142 HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
8256349Sqs148142
8266349Sqs148142 HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
8276349Sqs148142 HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
8286349Sqs148142
8296349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx "
8306349Sqs148142 " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh));
8316349Sqs148142
8326349Sqs148142 goto hxge_map_regs_exit;
8336349Sqs148142
8346349Sqs148142 hxge_map_regs_fail3:
8356349Sqs148142 if (dev_regs->hxge_msix_regh) {
8366349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_msix_regh);
8376349Sqs148142 }
8386349Sqs148142
8396349Sqs148142 hxge_map_regs_fail2:
8406349Sqs148142 if (dev_regs->hxge_regh) {
8416349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_regh);
8426349Sqs148142 }
8436349Sqs148142
8446349Sqs148142 hxge_map_regs_fail1:
8456349Sqs148142 if (dev_regs->hxge_pciregh) {
8466349Sqs148142 ddi_regs_map_free(&dev_regs->hxge_pciregh);
8476349Sqs148142 }
8486349Sqs148142
8496349Sqs148142 hxge_map_regs_fail0:
8506349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory"));
8516349Sqs148142 kmem_free(dev_regs, sizeof (dev_regs_t));
8526349Sqs148142
8536349Sqs148142 hxge_map_regs_exit:
8546349Sqs148142 if (ddi_status != DDI_SUCCESS)
8556349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED);
8566349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs"));
8576349Sqs148142 return (status);
8586349Sqs148142 }
8596349Sqs148142
8606349Sqs148142 static void
hxge_unmap_regs(p_hxge_t hxgep)8616349Sqs148142 hxge_unmap_regs(p_hxge_t hxgep)
8626349Sqs148142 {
8636349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs"));
8646349Sqs148142 if (hxgep->dev_regs) {
8656349Sqs148142 if (hxgep->dev_regs->hxge_pciregh) {
8666349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8676349Sqs148142 "==> hxge_unmap_regs: bus"));
8686349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh);
8696349Sqs148142 hxgep->dev_regs->hxge_pciregh = NULL;
8706349Sqs148142 }
8716349Sqs148142
8726349Sqs148142 if (hxgep->dev_regs->hxge_regh) {
8736349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8746349Sqs148142 "==> hxge_unmap_regs: device registers"));
8756349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_regh);
8766349Sqs148142 hxgep->dev_regs->hxge_regh = NULL;
8776349Sqs148142 }
8786349Sqs148142
8796349Sqs148142 if (hxgep->dev_regs->hxge_msix_regh) {
8806349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8816349Sqs148142 "==> hxge_unmap_regs: device interrupts"));
8826349Sqs148142 ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh);
8836349Sqs148142 hxgep->dev_regs->hxge_msix_regh = NULL;
8846349Sqs148142 }
8856349Sqs148142 kmem_free(hxgep->dev_regs, sizeof (dev_regs_t));
8866349Sqs148142 hxgep->dev_regs = NULL;
8876349Sqs148142 }
8886349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs"));
8896349Sqs148142 }
8906349Sqs148142
8916349Sqs148142 static hxge_status_t
hxge_setup_mutexes(p_hxge_t hxgep)8926349Sqs148142 hxge_setup_mutexes(p_hxge_t hxgep)
8936349Sqs148142 {
8946349Sqs148142 int ddi_status = DDI_SUCCESS;
8956349Sqs148142 hxge_status_t status = HXGE_OK;
8966349Sqs148142
8976349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes"));
8986349Sqs148142
8996349Sqs148142 /*
9006349Sqs148142 * Get the interrupt cookie so the mutexes can be Initialised.
9016349Sqs148142 */
9026349Sqs148142 ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0,
9036349Sqs148142 &hxgep->interrupt_cookie);
9046349Sqs148142
9056349Sqs148142 if (ddi_status != DDI_SUCCESS) {
9066349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9076349Sqs148142 "<== hxge_setup_mutexes: failed 0x%x", ddi_status));
9086349Sqs148142 goto hxge_setup_mutexes_exit;
9096349Sqs148142 }
9106349Sqs148142
9116349Sqs148142 /*
9126349Sqs148142 * Initialize mutex's for this device.
9136349Sqs148142 */
9146349Sqs148142 MUTEX_INIT(hxgep->genlock, NULL,
9156349Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
91610091SMichael.Speer@Sun.COM MUTEX_INIT(&hxgep->vmac_lock, NULL,
91710091SMichael.Speer@Sun.COM MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9186349Sqs148142 MUTEX_INIT(&hxgep->ouraddr_lock, NULL,
9196349Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9206349Sqs148142 RW_INIT(&hxgep->filter_lock, NULL,
9216349Sqs148142 RW_DRIVER, (void *) hxgep->interrupt_cookie);
9226864Sqs148142 MUTEX_INIT(&hxgep->pio_lock, NULL,
9236864Sqs148142 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9247584SQiyan.Sun@Sun.COM MUTEX_INIT(&hxgep->timeout.lock, NULL,
9257584SQiyan.Sun@Sun.COM MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9266349Sqs148142
9276349Sqs148142 hxge_setup_mutexes_exit:
9286349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
9296349Sqs148142 "<== hxge_setup_mutexes status = %x", status));
9306349Sqs148142
9316349Sqs148142 if (ddi_status != DDI_SUCCESS)
9326349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED);
9336349Sqs148142
9346349Sqs148142 return (status);
9356349Sqs148142 }
9366349Sqs148142
9376349Sqs148142 static void
hxge_destroy_mutexes(p_hxge_t hxgep)9386349Sqs148142 hxge_destroy_mutexes(p_hxge_t hxgep)
9396349Sqs148142 {
9406349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes"));
9416349Sqs148142 RW_DESTROY(&hxgep->filter_lock);
94210091SMichael.Speer@Sun.COM MUTEX_DESTROY(&hxgep->vmac_lock);
9436349Sqs148142 MUTEX_DESTROY(&hxgep->ouraddr_lock);
9446349Sqs148142 MUTEX_DESTROY(hxgep->genlock);
9456864Sqs148142 MUTEX_DESTROY(&hxgep->pio_lock);
9467584SQiyan.Sun@Sun.COM MUTEX_DESTROY(&hxgep->timeout.lock);
9476349Sqs148142
9486349Sqs148142 if (hxge_debug_init == 1) {
9496349Sqs148142 MUTEX_DESTROY(&hxgedebuglock);
9506349Sqs148142 hxge_debug_init = 0;
9516349Sqs148142 }
9526349Sqs148142
9536349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes"));
9546349Sqs148142 }
9556349Sqs148142
9566349Sqs148142 hxge_status_t
hxge_init(p_hxge_t hxgep)9576349Sqs148142 hxge_init(p_hxge_t hxgep)
9586349Sqs148142 {
9596349Sqs148142 hxge_status_t status = HXGE_OK;
9606349Sqs148142
9616349Sqs148142 HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init"));
9626349Sqs148142
9636349Sqs148142 if (hxgep->drv_state & STATE_HW_INITIALIZED) {
9646349Sqs148142 return (status);
9656349Sqs148142 }
9666349Sqs148142
9676349Sqs148142 /*
9686349Sqs148142 * Allocate system memory for the receive/transmit buffer blocks and
9696349Sqs148142 * receive/transmit descriptor rings.
9706349Sqs148142 */
9716349Sqs148142 status = hxge_alloc_mem_pool(hxgep);
9726349Sqs148142 if (status != HXGE_OK) {
9736349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n"));
9746349Sqs148142 goto hxge_init_fail1;
9756349Sqs148142 }
9766349Sqs148142
9776349Sqs148142 /*
9786349Sqs148142 * Initialize and enable TXDMA channels.
9796349Sqs148142 */
9806349Sqs148142 status = hxge_init_txdma_channels(hxgep);
9816349Sqs148142 if (status != HXGE_OK) {
9826349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n"));
9836349Sqs148142 goto hxge_init_fail3;
9846349Sqs148142 }
9856349Sqs148142
9866349Sqs148142 /*
9876349Sqs148142 * Initialize and enable RXDMA channels.
9886349Sqs148142 */
9896349Sqs148142 status = hxge_init_rxdma_channels(hxgep);
9906349Sqs148142 if (status != HXGE_OK) {
9916349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n"));
9926349Sqs148142 goto hxge_init_fail4;
9936349Sqs148142 }
9946349Sqs148142
9956349Sqs148142 /*
9966349Sqs148142 * Initialize TCAM
9976349Sqs148142 */
9986349Sqs148142 status = hxge_classify_init(hxgep);
9996349Sqs148142 if (status != HXGE_OK) {
10006349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n"));
10016349Sqs148142 goto hxge_init_fail5;
10026349Sqs148142 }
10036349Sqs148142
10046349Sqs148142 /*
10056349Sqs148142 * Initialize the VMAC block.
10066349Sqs148142 */
10076349Sqs148142 status = hxge_vmac_init(hxgep);
10086349Sqs148142 if (status != HXGE_OK) {
10096349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n"));
10106349Sqs148142 goto hxge_init_fail5;
10116349Sqs148142 }
10126349Sqs148142
10136349Sqs148142 /* Bringup - this may be unnecessary when PXE and FCODE available */
10146349Sqs148142 status = hxge_pfc_set_default_mac_addr(hxgep);
10156349Sqs148142 if (status != HXGE_OK) {
10166349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
10176349Sqs148142 "Default Address Failure\n"));
10186349Sqs148142 goto hxge_init_fail5;
10196349Sqs148142 }
10206349Sqs148142
10216349Sqs148142 /*
10226349Sqs148142 * Enable hardware interrupts.
10236349Sqs148142 */
10246349Sqs148142 hxge_intr_hw_enable(hxgep);
10256349Sqs148142 hxgep->drv_state |= STATE_HW_INITIALIZED;
10266349Sqs148142
10276349Sqs148142 goto hxge_init_exit;
10286349Sqs148142
10296349Sqs148142 hxge_init_fail5:
10306349Sqs148142 hxge_uninit_rxdma_channels(hxgep);
10316349Sqs148142 hxge_init_fail4:
10326349Sqs148142 hxge_uninit_txdma_channels(hxgep);
10336349Sqs148142 hxge_init_fail3:
10346349Sqs148142 hxge_free_mem_pool(hxgep);
10356349Sqs148142 hxge_init_fail1:
10366349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
10376349Sqs148142 "<== hxge_init status (failed) = 0x%08x", status));
10386349Sqs148142 return (status);
10396349Sqs148142
10406349Sqs148142 hxge_init_exit:
10416349Sqs148142
10426349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x",
10436349Sqs148142 status));
10446349Sqs148142
10456349Sqs148142 return (status);
10466349Sqs148142 }
10476349Sqs148142
10486349Sqs148142 timeout_id_t
hxge_start_timer(p_hxge_t hxgep,fptrv_t func,int msec)10496349Sqs148142 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec)
10506349Sqs148142 {
10516349Sqs148142 if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) {
10526349Sqs148142 return (timeout(func, (caddr_t)hxgep,
10536349Sqs148142 drv_usectohz(1000 * msec)));
10546349Sqs148142 }
10556349Sqs148142 return (NULL);
10566349Sqs148142 }
10576349Sqs148142
10586349Sqs148142 /*ARGSUSED*/
10596349Sqs148142 void
hxge_stop_timer(p_hxge_t hxgep,timeout_id_t timerid)10606349Sqs148142 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid)
10616349Sqs148142 {
10626349Sqs148142 if (timerid) {
10636349Sqs148142 (void) untimeout(timerid);
10646349Sqs148142 }
10656349Sqs148142 }
10666349Sqs148142
10676349Sqs148142 void
hxge_uninit(p_hxge_t hxgep)10686349Sqs148142 hxge_uninit(p_hxge_t hxgep)
10696349Sqs148142 {
10706349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit"));
10716349Sqs148142
10726349Sqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
10736349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
10746349Sqs148142 "==> hxge_uninit: not initialized"));
10756349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
10766349Sqs148142 return;
10776349Sqs148142 }
10786349Sqs148142
10796349Sqs148142 /* Stop timer */
10806349Sqs148142 if (hxgep->hxge_timerid) {
10816349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid);
10826349Sqs148142 hxgep->hxge_timerid = 0;
10836349Sqs148142 }
10846349Sqs148142
10856349Sqs148142 (void) hxge_intr_hw_disable(hxgep);
10866349Sqs148142
10876349Sqs148142 /* Reset the receive VMAC side. */
10886349Sqs148142 (void) hxge_rx_vmac_disable(hxgep);
10896349Sqs148142
10906349Sqs148142 /* Free classification resources */
10916349Sqs148142 (void) hxge_classify_uninit(hxgep);
10926349Sqs148142
10936349Sqs148142 /* Reset the transmit/receive DMA side. */
10946349Sqs148142 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP);
10956349Sqs148142 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP);
10966349Sqs148142
10976349Sqs148142 hxge_uninit_txdma_channels(hxgep);
10986349Sqs148142 hxge_uninit_rxdma_channels(hxgep);
10996349Sqs148142
11006349Sqs148142 /* Reset the transmit VMAC side. */
11016349Sqs148142 (void) hxge_tx_vmac_disable(hxgep);
11026349Sqs148142
11036349Sqs148142 hxge_free_mem_pool(hxgep);
11046349Sqs148142
11056349Sqs148142 hxgep->drv_state &= ~STATE_HW_INITIALIZED;
11066349Sqs148142
11076349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
11086349Sqs148142 }
11096349Sqs148142
11106349Sqs148142 /*ARGSUSED*/
11116349Sqs148142 /*VARARGS*/
11126349Sqs148142 void
hxge_debug_msg(p_hxge_t hxgep,uint64_t level,char * fmt,...)11136349Sqs148142 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...)
11146349Sqs148142 {
11156349Sqs148142 char msg_buffer[1048];
11166349Sqs148142 char prefix_buffer[32];
11176349Sqs148142 int instance;
11186349Sqs148142 uint64_t debug_level;
11196349Sqs148142 int cmn_level = CE_CONT;
11206349Sqs148142 va_list ap;
11216349Sqs148142
11226349Sqs148142 debug_level = (hxgep == NULL) ? hxge_debug_level :
11236349Sqs148142 hxgep->hxge_debug_level;
11246349Sqs148142
11256349Sqs148142 if ((level & debug_level) || (level == HXGE_NOTE) ||
11266349Sqs148142 (level == HXGE_ERR_CTL)) {
11276349Sqs148142 /* do the msg processing */
11286349Sqs148142 if (hxge_debug_init == 0) {
11296349Sqs148142 MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL);
11306349Sqs148142 hxge_debug_init = 1;
11316349Sqs148142 }
11326349Sqs148142
11336349Sqs148142 MUTEX_ENTER(&hxgedebuglock);
11346349Sqs148142
11356349Sqs148142 if ((level & HXGE_NOTE)) {
11366349Sqs148142 cmn_level = CE_NOTE;
11376349Sqs148142 }
11386349Sqs148142
11396349Sqs148142 if (level & HXGE_ERR_CTL) {
11406349Sqs148142 cmn_level = CE_WARN;
11416349Sqs148142 }
11426349Sqs148142
11436349Sqs148142 va_start(ap, fmt);
11446349Sqs148142 (void) vsprintf(msg_buffer, fmt, ap);
11456349Sqs148142 va_end(ap);
11466349Sqs148142
11476349Sqs148142 if (hxgep == NULL) {
11486349Sqs148142 instance = -1;
11496349Sqs148142 (void) sprintf(prefix_buffer, "%s :", "hxge");
11506349Sqs148142 } else {
11516349Sqs148142 instance = hxgep->instance;
11526349Sqs148142 (void) sprintf(prefix_buffer,
11536349Sqs148142 "%s%d :", "hxge", instance);
11546349Sqs148142 }
11556349Sqs148142
11566349Sqs148142 MUTEX_EXIT(&hxgedebuglock);
11576349Sqs148142 cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer);
11586349Sqs148142 }
11596349Sqs148142 }
11606349Sqs148142
11616349Sqs148142 char *
hxge_dump_packet(char * addr,int size)11626349Sqs148142 hxge_dump_packet(char *addr, int size)
11636349Sqs148142 {
11646349Sqs148142 uchar_t *ap = (uchar_t *)addr;
11656349Sqs148142 int i;
11666349Sqs148142 static char etherbuf[1024];
11676349Sqs148142 char *cp = etherbuf;
11686349Sqs148142 char digits[] = "0123456789abcdef";
11696349Sqs148142
11706349Sqs148142 if (!size)
11716349Sqs148142 size = 60;
11726349Sqs148142
11736349Sqs148142 if (size > MAX_DUMP_SZ) {
11746349Sqs148142 /* Dump the leading bytes */
11756349Sqs148142 for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11766349Sqs148142 if (*ap > 0x0f)
11776349Sqs148142 *cp++ = digits[*ap >> 4];
11786349Sqs148142 *cp++ = digits[*ap++ & 0xf];
11796349Sqs148142 *cp++ = ':';
11806349Sqs148142 }
11816349Sqs148142 for (i = 0; i < 20; i++)
11826349Sqs148142 *cp++ = '.';
11836349Sqs148142 /* Dump the last MAX_DUMP_SZ/2 bytes */
11846349Sqs148142 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2));
11856349Sqs148142 for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11866349Sqs148142 if (*ap > 0x0f)
11876349Sqs148142 *cp++ = digits[*ap >> 4];
11886349Sqs148142 *cp++ = digits[*ap++ & 0xf];
11896349Sqs148142 *cp++ = ':';
11906349Sqs148142 }
11916349Sqs148142 } else {
11926349Sqs148142 for (i = 0; i < size; i++) {
11936349Sqs148142 if (*ap > 0x0f)
11946349Sqs148142 *cp++ = digits[*ap >> 4];
11956349Sqs148142 *cp++ = digits[*ap++ & 0xf];
11966349Sqs148142 *cp++ = ':';
11976349Sqs148142 }
11986349Sqs148142 }
11996349Sqs148142 *--cp = 0;
12006349Sqs148142 return (etherbuf);
12016349Sqs148142 }
12026349Sqs148142
12036349Sqs148142 static void
hxge_suspend(p_hxge_t hxgep)12046349Sqs148142 hxge_suspend(p_hxge_t hxgep)
12056349Sqs148142 {
12066349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend"));
12076349Sqs148142
12088236SQiyan.Sun@Sun.COM /*
12098236SQiyan.Sun@Sun.COM * Stop the link status timer before hxge_intrs_disable() to avoid
12108236SQiyan.Sun@Sun.COM * accessing the the MSIX table simultaneously. Note that the timer
12118236SQiyan.Sun@Sun.COM * routine polls for MSIX parity errors.
12128236SQiyan.Sun@Sun.COM */
12137584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock);
12147584SQiyan.Sun@Sun.COM if (hxgep->timeout.id)
12157584SQiyan.Sun@Sun.COM (void) untimeout(hxgep->timeout.id);
12167584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock);
12177584SQiyan.Sun@Sun.COM
12188236SQiyan.Sun@Sun.COM hxge_intrs_disable(hxgep);
12198236SQiyan.Sun@Sun.COM hxge_destroy_dev(hxgep);
12208236SQiyan.Sun@Sun.COM
12216349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend"));
12226349Sqs148142 }
12236349Sqs148142
12246349Sqs148142 static hxge_status_t
hxge_resume(p_hxge_t hxgep)12256349Sqs148142 hxge_resume(p_hxge_t hxgep)
12266349Sqs148142 {
12276349Sqs148142 hxge_status_t status = HXGE_OK;
12286349Sqs148142
12296349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume"));
12306349Sqs148142 hxgep->suspended = DDI_RESUME;
12316349Sqs148142
12326349Sqs148142 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START);
12336349Sqs148142 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START);
12346349Sqs148142
12356349Sqs148142 (void) hxge_rx_vmac_enable(hxgep);
12366349Sqs148142 (void) hxge_tx_vmac_enable(hxgep);
12376349Sqs148142
12386349Sqs148142 hxge_intrs_enable(hxgep);
12396349Sqs148142
12406349Sqs148142 hxgep->suspended = 0;
12416349Sqs148142
12428236SQiyan.Sun@Sun.COM /*
12438236SQiyan.Sun@Sun.COM * Resume the link status timer after hxge_intrs_enable to avoid
12448236SQiyan.Sun@Sun.COM * accessing MSIX table simultaneously.
12458236SQiyan.Sun@Sun.COM */
12467584SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock);
12477584SQiyan.Sun@Sun.COM hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
12487584SQiyan.Sun@Sun.COM hxgep->timeout.ticks);
12497584SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock);
12507584SQiyan.Sun@Sun.COM
12516349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12526349Sqs148142 "<== hxge_resume status = 0x%x", status));
12536349Sqs148142
12546349Sqs148142 return (status);
12556349Sqs148142 }
12566349Sqs148142
125711257SMichael.Speer@Sun.COM static hxge_status_t
hxge_setup_dev(p_hxge_t hxgep)12586349Sqs148142 hxge_setup_dev(p_hxge_t hxgep)
12596349Sqs148142 {
12606349Sqs148142 hxge_status_t status = HXGE_OK;
12616349Sqs148142
12626349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev"));
12636349Sqs148142
12646349Sqs148142 status = hxge_link_init(hxgep);
12656349Sqs148142 if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) {
12666349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
12676349Sqs148142 "Bad register acc handle"));
12686349Sqs148142 status = HXGE_ERROR;
12696349Sqs148142 }
12706349Sqs148142
12716349Sqs148142 if (status != HXGE_OK) {
12726349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL,
12736349Sqs148142 " hxge_setup_dev status (link init 0x%08x)", status));
12746349Sqs148142 goto hxge_setup_dev_exit;
12756349Sqs148142 }
12766349Sqs148142
12776349Sqs148142 hxge_setup_dev_exit:
12786349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12796349Sqs148142 "<== hxge_setup_dev status = 0x%08x", status));
12806349Sqs148142
12816349Sqs148142 return (status);
12826349Sqs148142 }
12836349Sqs148142
12846349Sqs148142 static void
hxge_destroy_dev(p_hxge_t hxgep)12856349Sqs148142 hxge_destroy_dev(p_hxge_t hxgep)
12866349Sqs148142 {
12876349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev"));
12886349Sqs148142
12896349Sqs148142 (void) hxge_hw_stop(hxgep);
12906349Sqs148142
12916349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev"));
12926349Sqs148142 }
12936349Sqs148142
12946349Sqs148142 static hxge_status_t
hxge_setup_system_dma_pages(p_hxge_t hxgep)12956349Sqs148142 hxge_setup_system_dma_pages(p_hxge_t hxgep)
12966349Sqs148142 {
12976349Sqs148142 int ddi_status = DDI_SUCCESS;
12986349Sqs148142 uint_t count;
12996349Sqs148142 ddi_dma_cookie_t cookie;
13006349Sqs148142 uint_t iommu_pagesize;
13016349Sqs148142 hxge_status_t status = HXGE_OK;
13026349Sqs148142
13036349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages"));
13046349Sqs148142
13056349Sqs148142 hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1);
13066349Sqs148142 iommu_pagesize = dvma_pagesize(hxgep->dip);
13076349Sqs148142
13086349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13096349Sqs148142 " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13106349Sqs148142 " default_block_size %d iommu_pagesize %d",
13116349Sqs148142 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13126349Sqs148142 hxgep->rx_default_block_size, iommu_pagesize));
13136349Sqs148142
13146349Sqs148142 if (iommu_pagesize != 0) {
13156349Sqs148142 if (hxgep->sys_page_sz == iommu_pagesize) {
13166349Sqs148142 /* Hydra support up to 8K pages */
13176349Sqs148142 if (iommu_pagesize > 0x2000)
13186349Sqs148142 hxgep->sys_page_sz = 0x2000;
13196349Sqs148142 } else {
13206349Sqs148142 if (hxgep->sys_page_sz > iommu_pagesize)
13216349Sqs148142 hxgep->sys_page_sz = iommu_pagesize;
13226349Sqs148142 }
13236349Sqs148142 }
13246349Sqs148142
13256349Sqs148142 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13266349Sqs148142
13276349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13286349Sqs148142 "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13296349Sqs148142 "default_block_size %d page mask %d",
13306349Sqs148142 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13316349Sqs148142 hxgep->rx_default_block_size, hxgep->sys_page_mask));
13326349Sqs148142
13336349Sqs148142 switch (hxgep->sys_page_sz) {
13346349Sqs148142 default:
13356349Sqs148142 hxgep->sys_page_sz = 0x1000;
13366349Sqs148142 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13376349Sqs148142 hxgep->rx_default_block_size = 0x1000;
13386349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13396349Sqs148142 break;
13406349Sqs148142 case 0x1000:
13416349Sqs148142 hxgep->rx_default_block_size = 0x1000;
13426349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13436349Sqs148142 break;
13446349Sqs148142 case 0x2000:
13456349Sqs148142 hxgep->rx_default_block_size = 0x2000;
13466349Sqs148142 hxgep->rx_bksize_code = RBR_BKSIZE_8K;
13476349Sqs148142 break;
13486349Sqs148142 }
13496349Sqs148142
13506349Sqs148142 hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13516349Sqs148142 hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13526349Sqs148142
13536349Sqs148142 /*
13546349Sqs148142 * Get the system DMA burst size.
13556349Sqs148142 */
13566349Sqs148142 ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr,
13576349Sqs148142 DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle);
13586349Sqs148142 if (ddi_status != DDI_SUCCESS) {
13596349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13606349Sqs148142 "ddi_dma_alloc_handle: failed status 0x%x", ddi_status));
13616349Sqs148142 goto hxge_get_soft_properties_exit;
13626349Sqs148142 }
13636349Sqs148142
13646349Sqs148142 ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL,
13656349Sqs148142 (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle),
13666349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
13676349Sqs148142 &cookie, &count);
13686349Sqs148142 if (ddi_status != DDI_DMA_MAPPED) {
13696349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13706349Sqs148142 "Binding spare handle to find system burstsize failed."));
13716349Sqs148142 ddi_status = DDI_FAILURE;
13726349Sqs148142 goto hxge_get_soft_properties_fail1;
13736349Sqs148142 }
13746349Sqs148142
13756349Sqs148142 hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle);
13766349Sqs148142 (void) ddi_dma_unbind_handle(hxgep->dmasparehandle);
13776349Sqs148142
13786349Sqs148142 hxge_get_soft_properties_fail1:
13796349Sqs148142 ddi_dma_free_handle(&hxgep->dmasparehandle);
13806349Sqs148142
13816349Sqs148142 hxge_get_soft_properties_exit:
13826349Sqs148142
13836349Sqs148142 if (ddi_status != DDI_SUCCESS)
13846349Sqs148142 status |= (HXGE_ERROR | HXGE_DDI_FAILED);
13856349Sqs148142
13866349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13876349Sqs148142 "<== hxge_setup_system_dma_pages status = 0x%08x", status));
13886349Sqs148142
13896349Sqs148142 return (status);
13906349Sqs148142 }
13916349Sqs148142
139211257SMichael.Speer@Sun.COM static hxge_status_t
hxge_alloc_mem_pool(p_hxge_t hxgep)13936349Sqs148142 hxge_alloc_mem_pool(p_hxge_t hxgep)
13946349Sqs148142 {
13956349Sqs148142 hxge_status_t status = HXGE_OK;
13966349Sqs148142
13976349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool"));
13986349Sqs148142
13996349Sqs148142 status = hxge_alloc_rx_mem_pool(hxgep);
14006349Sqs148142 if (status != HXGE_OK) {
14016349Sqs148142 return (HXGE_ERROR);
14026349Sqs148142 }
14036349Sqs148142
14046349Sqs148142 status = hxge_alloc_tx_mem_pool(hxgep);
14056349Sqs148142 if (status != HXGE_OK) {
14066349Sqs148142 hxge_free_rx_mem_pool(hxgep);
14076349Sqs148142 return (HXGE_ERROR);
14086349Sqs148142 }
14096349Sqs148142
14106349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool"));
14116349Sqs148142 return (HXGE_OK);
14126349Sqs148142 }
14136349Sqs148142
14146349Sqs148142 static void
hxge_free_mem_pool(p_hxge_t hxgep)14156349Sqs148142 hxge_free_mem_pool(p_hxge_t hxgep)
14166349Sqs148142 {
14176349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool"));
14186349Sqs148142
14196349Sqs148142 hxge_free_rx_mem_pool(hxgep);
14206349Sqs148142 hxge_free_tx_mem_pool(hxgep);
14216349Sqs148142
14226349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool"));
14236349Sqs148142 }
14246349Sqs148142
14256349Sqs148142 static hxge_status_t
hxge_alloc_rx_mem_pool(p_hxge_t hxgep)14266349Sqs148142 hxge_alloc_rx_mem_pool(p_hxge_t hxgep)
14276349Sqs148142 {
14286349Sqs148142 int i, j;
14296349Sqs148142 uint32_t ndmas, st_rdc;
14306349Sqs148142 p_hxge_dma_pt_cfg_t p_all_cfgp;
14316349Sqs148142 p_hxge_hw_pt_cfg_t p_cfgp;
14326349Sqs148142 p_hxge_dma_pool_t dma_poolp;
14336349Sqs148142 p_hxge_dma_common_t *dma_buf_p;
14347618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rbr_cntl_poolp;
14357618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rbr_cntl_p;
14367618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rcr_cntl_poolp;
14377618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rcr_cntl_p;
14387618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_mbox_cntl_poolp;
14397618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_mbox_cntl_p;
14406349Sqs148142 size_t rx_buf_alloc_size;
14417618SMichael.Speer@Sun.COM size_t rx_rbr_cntl_alloc_size;
14427618SMichael.Speer@Sun.COM size_t rx_rcr_cntl_alloc_size;
14437618SMichael.Speer@Sun.COM size_t rx_mbox_cntl_alloc_size;
14446349Sqs148142 uint32_t *num_chunks; /* per dma */
14456349Sqs148142 hxge_status_t status = HXGE_OK;
14466349Sqs148142
14476349Sqs148142 uint32_t hxge_port_rbr_size;
14486349Sqs148142 uint32_t hxge_port_rbr_spare_size;
14496349Sqs148142 uint32_t hxge_port_rcr_size;
14506349Sqs148142
14516349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool"));
14526349Sqs148142
14536349Sqs148142 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
14546349Sqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
14556349Sqs148142 st_rdc = p_cfgp->start_rdc;
14566349Sqs148142 ndmas = p_cfgp->max_rdcs;
14576349Sqs148142
14586349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
14596349Sqs148142 " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
14606349Sqs148142
14616349Sqs148142 /*
14626349Sqs148142 * Allocate memory for each receive DMA channel.
14636349Sqs148142 */
14646349Sqs148142 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
14656349Sqs148142 KM_SLEEP);
14666349Sqs148142 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14676349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14686349Sqs148142
14697618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp = (p_hxge_dma_pool_t)
14707618SMichael.Speer@Sun.COM KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14717618SMichael.Speer@Sun.COM dma_rbr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14727618SMichael.Speer@Sun.COM sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14737618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp = (p_hxge_dma_pool_t)
14746349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14757618SMichael.Speer@Sun.COM dma_rcr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14767618SMichael.Speer@Sun.COM sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14777618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp = (p_hxge_dma_pool_t)
14787618SMichael.Speer@Sun.COM KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14797618SMichael.Speer@Sun.COM dma_mbox_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14806349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14816349Sqs148142
14826349Sqs148142 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
14836349Sqs148142 KM_SLEEP);
14846349Sqs148142
14856349Sqs148142 /*
14866349Sqs148142 * Assume that each DMA channel will be configured with default block
14876349Sqs148142 * size. rbr block counts are mod of batch count (16).
14886349Sqs148142 */
14896349Sqs148142 hxge_port_rbr_size = p_all_cfgp->rbr_size;
14906349Sqs148142 hxge_port_rcr_size = p_all_cfgp->rcr_size;
14916349Sqs148142
14926349Sqs148142 if (!hxge_port_rbr_size) {
14936349Sqs148142 hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT;
14946349Sqs148142 }
14956349Sqs148142
14966349Sqs148142 if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) {
14976349Sqs148142 hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH *
14986349Sqs148142 (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1));
14996349Sqs148142 }
15006349Sqs148142
15016349Sqs148142 p_all_cfgp->rbr_size = hxge_port_rbr_size;
15026349Sqs148142 hxge_port_rbr_spare_size = hxge_rbr_spare_size;
15036349Sqs148142
15046349Sqs148142 if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) {
15056349Sqs148142 hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH *
15066349Sqs148142 (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1));
15076349Sqs148142 }
15086349Sqs148142
15096349Sqs148142 rx_buf_alloc_size = (hxgep->rx_default_block_size *
15106349Sqs148142 (hxge_port_rbr_size + hxge_port_rbr_spare_size));
15116349Sqs148142
15126349Sqs148142 /*
15136349Sqs148142 * Addresses of receive block ring, receive completion ring and the
15146349Sqs148142 * mailbox must be all cache-aligned (64 bytes).
15156349Sqs148142 */
15167618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size;
15177618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size *= sizeof (rx_desc_t);
15187618SMichael.Speer@Sun.COM rx_rcr_cntl_alloc_size = sizeof (rcr_entry_t) * hxge_port_rcr_size;
15197618SMichael.Speer@Sun.COM rx_mbox_cntl_alloc_size = sizeof (rxdma_mailbox_t);
15206349Sqs148142
15216349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: "
15226349Sqs148142 "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d "
15236349Sqs148142 "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d",
15246349Sqs148142 hxge_port_rbr_size, hxge_port_rbr_spare_size,
15256349Sqs148142 hxge_port_rcr_size, rx_cntl_alloc_size));
15266349Sqs148142
15276349Sqs148142 hxgep->hxge_port_rbr_size = hxge_port_rbr_size;
15286349Sqs148142 hxgep->hxge_port_rcr_size = hxge_port_rcr_size;
15296349Sqs148142
15306349Sqs148142 /*
15316349Sqs148142 * Allocate memory for receive buffers and descriptor rings. Replace
15326349Sqs148142 * allocation functions with interface functions provided by the
15336349Sqs148142 * partition manager when it is available.
15346349Sqs148142 */
15356349Sqs148142 /*
15366349Sqs148142 * Allocate memory for the receive buffer blocks.
15376349Sqs148142 */
15386349Sqs148142 for (i = 0; i < ndmas; i++) {
15396349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15406349Sqs148142 " hxge_alloc_rx_mem_pool to alloc mem: "
15416349Sqs148142 " dma %d dma_buf_p %llx &dma_buf_p %llx",
15426349Sqs148142 i, dma_buf_p[i], &dma_buf_p[i]));
15436349Sqs148142
15446349Sqs148142 num_chunks[i] = 0;
15456349Sqs148142
15466349Sqs148142 status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i],
15476349Sqs148142 rx_buf_alloc_size, hxgep->rx_default_block_size,
15486349Sqs148142 &num_chunks[i]);
15496349Sqs148142 if (status != HXGE_OK) {
15506349Sqs148142 break;
15516349Sqs148142 }
15526349Sqs148142
15536349Sqs148142 st_rdc++;
15546349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15556349Sqs148142 " hxge_alloc_rx_mem_pool DONE alloc mem: "
15566349Sqs148142 "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
15576349Sqs148142 dma_buf_p[i], &dma_buf_p[i]));
15586349Sqs148142 }
15596349Sqs148142
15606349Sqs148142 if (i < ndmas) {
15616349Sqs148142 goto hxge_alloc_rx_mem_fail1;
15626349Sqs148142 }
15636349Sqs148142
15646349Sqs148142 /*
15656349Sqs148142 * Allocate memory for descriptor rings and mailbox.
15666349Sqs148142 */
15676349Sqs148142 st_rdc = p_cfgp->start_rdc;
15686349Sqs148142 for (j = 0; j < ndmas; j++) {
15697618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15707618SMichael.Speer@Sun.COM &dma_rbr_cntl_p[j], &hxge_rx_rbr_desc_dma_attr,
15717618SMichael.Speer@Sun.COM rx_rbr_cntl_alloc_size)) != HXGE_OK) {
15727618SMichael.Speer@Sun.COM break;
15737618SMichael.Speer@Sun.COM }
15747618SMichael.Speer@Sun.COM
15757618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15767618SMichael.Speer@Sun.COM &dma_rcr_cntl_p[j], &hxge_rx_rcr_desc_dma_attr,
15777618SMichael.Speer@Sun.COM rx_rcr_cntl_alloc_size)) != HXGE_OK) {
15787618SMichael.Speer@Sun.COM break;
15797618SMichael.Speer@Sun.COM }
15807618SMichael.Speer@Sun.COM
15817618SMichael.Speer@Sun.COM if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15827618SMichael.Speer@Sun.COM &dma_mbox_cntl_p[j], &hxge_rx_mbox_dma_attr,
15837618SMichael.Speer@Sun.COM rx_mbox_cntl_alloc_size)) != HXGE_OK) {
15846349Sqs148142 break;
15856349Sqs148142 }
15866349Sqs148142 st_rdc++;
15876349Sqs148142 }
15886349Sqs148142
15896349Sqs148142 if (j < ndmas) {
15906349Sqs148142 goto hxge_alloc_rx_mem_fail2;
15916349Sqs148142 }
15926349Sqs148142
15936349Sqs148142 dma_poolp->ndmas = ndmas;
15946349Sqs148142 dma_poolp->num_chunks = num_chunks;
15956349Sqs148142 dma_poolp->buf_allocated = B_TRUE;
15966349Sqs148142 hxgep->rx_buf_pool_p = dma_poolp;
15976349Sqs148142 dma_poolp->dma_buf_pool_p = dma_buf_p;
15986349Sqs148142
15997618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->ndmas = ndmas;
16007618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->buf_allocated = B_TRUE;
16017618SMichael.Speer@Sun.COM hxgep->rx_rbr_cntl_pool_p = dma_rbr_cntl_poolp;
16027618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp->dma_buf_pool_p = dma_rbr_cntl_p;
16037618SMichael.Speer@Sun.COM
16047618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->ndmas = ndmas;
16057618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->buf_allocated = B_TRUE;
16067618SMichael.Speer@Sun.COM hxgep->rx_rcr_cntl_pool_p = dma_rcr_cntl_poolp;
16077618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp->dma_buf_pool_p = dma_rcr_cntl_p;
16087618SMichael.Speer@Sun.COM
16097618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->ndmas = ndmas;
16107618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->buf_allocated = B_TRUE;
16117618SMichael.Speer@Sun.COM hxgep->rx_mbox_cntl_pool_p = dma_mbox_cntl_poolp;
16127618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp->dma_buf_pool_p = dma_mbox_cntl_p;
16136349Sqs148142
16146349Sqs148142 goto hxge_alloc_rx_mem_pool_exit;
16156349Sqs148142
16166349Sqs148142 hxge_alloc_rx_mem_fail2:
16176349Sqs148142 /* Free control buffers */
16186349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16196349Sqs148142 "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
16206349Sqs148142 for (; j >= 0; j--) {
16216349Sqs148142 hxge_free_rx_cntl_dma(hxgep,
16227618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_rbr_cntl_p[j]);
16237618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep,
16247618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_rcr_cntl_p[j]);
16257618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep,
16267618SMichael.Speer@Sun.COM (p_hxge_dma_common_t)dma_mbox_cntl_p[j]);
16276349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16286349Sqs148142 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
16296349Sqs148142 }
16306349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16316349Sqs148142 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
16326349Sqs148142
16336349Sqs148142 hxge_alloc_rx_mem_fail1:
16346349Sqs148142 /* Free data buffers */
16356349Sqs148142 i--;
16366349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16376349Sqs148142 "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
16386349Sqs148142 for (; i >= 0; i--) {
16396349Sqs148142 hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
16406349Sqs148142 num_chunks[i]);
16416349Sqs148142 }
16426349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16436349Sqs148142 "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
16446349Sqs148142
16456349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
16466349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
16476349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
16487618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
16497618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16507618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
16517618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16527618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
16537618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16546349Sqs148142
16556349Sqs148142 hxge_alloc_rx_mem_pool_exit:
16566349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16576349Sqs148142 "<== hxge_alloc_rx_mem_pool:status 0x%08x", status));
16586349Sqs148142
16596349Sqs148142 return (status);
16606349Sqs148142 }
16616349Sqs148142
16626349Sqs148142 static void
hxge_free_rx_mem_pool(p_hxge_t hxgep)16636349Sqs148142 hxge_free_rx_mem_pool(p_hxge_t hxgep)
16646349Sqs148142 {
16656349Sqs148142 uint32_t i, ndmas;
16666349Sqs148142 p_hxge_dma_pool_t dma_poolp;
16676349Sqs148142 p_hxge_dma_common_t *dma_buf_p;
16687618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rbr_cntl_poolp;
16697618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rbr_cntl_p;
16707618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_rcr_cntl_poolp;
16717618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_rcr_cntl_p;
16727618SMichael.Speer@Sun.COM p_hxge_dma_pool_t dma_mbox_cntl_poolp;
16737618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dma_mbox_cntl_p;
16746349Sqs148142 uint32_t *num_chunks;
16756349Sqs148142
16766349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool"));
16776349Sqs148142
16786349Sqs148142 dma_poolp = hxgep->rx_buf_pool_p;
16796349Sqs148142 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
16806349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool "
16816349Sqs148142 "(null rx buf pool or buf not allocated"));
16826349Sqs148142 return;
16836349Sqs148142 }
16846349Sqs148142
16857618SMichael.Speer@Sun.COM dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p;
16867618SMichael.Speer@Sun.COM if (dma_rbr_cntl_poolp == NULL ||
16877618SMichael.Speer@Sun.COM (!dma_rbr_cntl_poolp->buf_allocated)) {
16886349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16896349Sqs148142 "<== hxge_free_rx_mem_pool "
16907618SMichael.Speer@Sun.COM "(null rbr cntl buf pool or rbr cntl buf not allocated"));
16917618SMichael.Speer@Sun.COM return;
16927618SMichael.Speer@Sun.COM }
16937618SMichael.Speer@Sun.COM
16947618SMichael.Speer@Sun.COM dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p;
16957618SMichael.Speer@Sun.COM if (dma_rcr_cntl_poolp == NULL ||
16967618SMichael.Speer@Sun.COM (!dma_rcr_cntl_poolp->buf_allocated)) {
16977618SMichael.Speer@Sun.COM HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16987618SMichael.Speer@Sun.COM "<== hxge_free_rx_mem_pool "
16997618SMichael.Speer@Sun.COM "(null rcr cntl buf pool or rcr cntl buf not allocated"));
17007618SMichael.Speer@Sun.COM return;
17017618SMichael.Speer@Sun.COM }
17027618SMichael.Speer@Sun.COM
17037618SMichael.Speer@Sun.COM dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p;
17047618SMichael.Speer@Sun.COM if (dma_mbox_cntl_poolp == NULL ||
17057618SMichael.Speer@Sun.COM (!dma_mbox_cntl_poolp->buf_allocated)) {
17067618SMichael.Speer@Sun.COM HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17077618SMichael.Speer@Sun.COM "<== hxge_free_rx_mem_pool "
17087618SMichael.Speer@Sun.COM "(null mbox cntl buf pool or mbox cntl buf not allocated"));
17096349Sqs148142 return;
17106349Sqs148142 }
17116349Sqs148142
17126349Sqs148142 dma_buf_p = dma_poolp->dma_buf_pool_p;
17136349Sqs148142 num_chunks = dma_poolp->num_chunks;
17146349Sqs148142
17157618SMichael.Speer@Sun.COM dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p;
17167618SMichael.Speer@Sun.COM dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p;
17177618SMichael.Speer@Sun.COM dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p;
17187618SMichael.Speer@Sun.COM ndmas = dma_rbr_cntl_poolp->ndmas;
17196349Sqs148142
17206349Sqs148142 for (i = 0; i < ndmas; i++) {
17216349Sqs148142 hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
17226349Sqs148142 }
17236349Sqs148142
17246349Sqs148142 for (i = 0; i < ndmas; i++) {
17257618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_rbr_cntl_p[i]);
17267618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_rcr_cntl_p[i]);
17277618SMichael.Speer@Sun.COM hxge_free_rx_cntl_dma(hxgep, dma_mbox_cntl_p[i]);
17286349Sqs148142 }
17296349Sqs148142
17306349Sqs148142 for (i = 0; i < ndmas; i++) {
17316349Sqs148142 KMEM_FREE(dma_buf_p[i],
17326349Sqs148142 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
17337618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p[i], sizeof (hxge_dma_common_t));
17347618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p[i], sizeof (hxge_dma_common_t));
17357618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p[i], sizeof (hxge_dma_common_t));
17366349Sqs148142 }
17376349Sqs148142
17386349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
17397618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17407618SMichael.Speer@Sun.COM KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
17417618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17427618SMichael.Speer@Sun.COM KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
17437618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17447618SMichael.Speer@Sun.COM KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
17456349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
17466349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
17476349Sqs148142
17486349Sqs148142 hxgep->rx_buf_pool_p = NULL;
17497618SMichael.Speer@Sun.COM hxgep->rx_rbr_cntl_pool_p = NULL;
17507618SMichael.Speer@Sun.COM hxgep->rx_rcr_cntl_pool_p = NULL;
17517618SMichael.Speer@Sun.COM hxgep->rx_mbox_cntl_pool_p = NULL;
17526349Sqs148142
17536349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool"));
17546349Sqs148142 }
17556349Sqs148142
17566349Sqs148142 static hxge_status_t
hxge_alloc_rx_buf_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t alloc_size,size_t block_size,uint32_t * num_chunks)17576349Sqs148142 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
17586349Sqs148142 p_hxge_dma_common_t *dmap,
17596349Sqs148142 size_t alloc_size, size_t block_size, uint32_t *num_chunks)
17606349Sqs148142 {
17616349Sqs148142 p_hxge_dma_common_t rx_dmap;
17626349Sqs148142 hxge_status_t status = HXGE_OK;
17636349Sqs148142 size_t total_alloc_size;
17646349Sqs148142 size_t allocated = 0;
17656349Sqs148142 int i, size_index, array_size;
17666349Sqs148142
17676349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma"));
17686349Sqs148142
17696349Sqs148142 rx_dmap = (p_hxge_dma_common_t)
17706349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
17716349Sqs148142
17726349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17736349Sqs148142 " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
17746349Sqs148142 dma_channel, alloc_size, block_size, dmap));
17756349Sqs148142
17766349Sqs148142 total_alloc_size = alloc_size;
17776349Sqs148142
17786349Sqs148142 i = 0;
17796349Sqs148142 size_index = 0;
17806349Sqs148142 array_size = sizeof (alloc_sizes) / sizeof (size_t);
17818141SMichael.Speer@Sun.COM while ((size_index < array_size) &&
17828141SMichael.Speer@Sun.COM (alloc_sizes[size_index] < alloc_size))
17836349Sqs148142 size_index++;
17846349Sqs148142 if (size_index >= array_size) {
17856349Sqs148142 size_index = array_size - 1;
17866349Sqs148142 }
17876349Sqs148142
17886349Sqs148142 while ((allocated < total_alloc_size) &&
17896349Sqs148142 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
17906349Sqs148142 rx_dmap[i].dma_chunk_index = i;
17916349Sqs148142 rx_dmap[i].block_size = block_size;
17926349Sqs148142 rx_dmap[i].alength = alloc_sizes[size_index];
17936349Sqs148142 rx_dmap[i].orig_alength = rx_dmap[i].alength;
17946349Sqs148142 rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
17956349Sqs148142 rx_dmap[i].dma_channel = dma_channel;
17966349Sqs148142 rx_dmap[i].contig_alloc_type = B_FALSE;
17976349Sqs148142
17986349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17996349Sqs148142 "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
18006349Sqs148142 "i %d nblocks %d alength %d",
18016349Sqs148142 dma_channel, i, &rx_dmap[i], block_size,
18026349Sqs148142 i, rx_dmap[i].nblocks, rx_dmap[i].alength));
18036349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
18046349Sqs148142 &hxge_rx_dma_attr, rx_dmap[i].alength,
18056349Sqs148142 &hxge_dev_buf_dma_acc_attr,
18066349Sqs148142 DDI_DMA_READ | DDI_DMA_STREAMING,
18076349Sqs148142 (p_hxge_dma_common_t)(&rx_dmap[i]));
18086349Sqs148142 if (status != HXGE_OK) {
18096349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18106349Sqs148142 " hxge_alloc_rx_buf_dma: Alloc Failed: "
18116349Sqs148142 " for size: %d", alloc_sizes[size_index]));
18126349Sqs148142 size_index--;
18136349Sqs148142 } else {
18146349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18156349Sqs148142 " alloc_rx_buf_dma allocated rdc %d "
18166349Sqs148142 "chunk %d size %x dvma %x bufp %llx ",
18176349Sqs148142 dma_channel, i, rx_dmap[i].alength,
18186349Sqs148142 rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
18196349Sqs148142 i++;
18206349Sqs148142 allocated += alloc_sizes[size_index];
18216349Sqs148142 }
18226349Sqs148142 }
18236349Sqs148142
18246349Sqs148142 if (allocated < total_alloc_size) {
18256349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
18266349Sqs148142 " hxge_alloc_rx_buf_dma failed due to"
18276349Sqs148142 " allocated(%d) < required(%d)",
18286349Sqs148142 allocated, total_alloc_size));
18296349Sqs148142 goto hxge_alloc_rx_mem_fail1;
18306349Sqs148142 }
18316349Sqs148142
18326349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18336349Sqs148142 " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i));
18346349Sqs148142
18356349Sqs148142 *num_chunks = i;
18366349Sqs148142 *dmap = rx_dmap;
18376349Sqs148142
18386349Sqs148142 goto hxge_alloc_rx_mem_exit;
18396349Sqs148142
18406349Sqs148142 hxge_alloc_rx_mem_fail1:
18416349Sqs148142 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
18426349Sqs148142
18436349Sqs148142 hxge_alloc_rx_mem_exit:
18446349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18456349Sqs148142 "<== hxge_alloc_rx_buf_dma status 0x%08x", status));
18466349Sqs148142
18476349Sqs148142 return (status);
18486349Sqs148142 }
18496349Sqs148142
18506349Sqs148142 /*ARGSUSED*/
18516349Sqs148142 static void
hxge_free_rx_buf_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap,uint32_t num_chunks)18526349Sqs148142 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
18536349Sqs148142 uint32_t num_chunks)
18546349Sqs148142 {
18556349Sqs148142 int i;
18566349Sqs148142
18576349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
18586349Sqs148142 "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks));
18596349Sqs148142
18606349Sqs148142 for (i = 0; i < num_chunks; i++) {
18616349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
18626349Sqs148142 "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap));
18636349Sqs148142 hxge_dma_mem_free(dmap++);
18646349Sqs148142 }
18656349Sqs148142
18666349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma"));
18676349Sqs148142 }
18686349Sqs148142
18696349Sqs148142 /*ARGSUSED*/
18706349Sqs148142 static hxge_status_t
hxge_alloc_rx_cntl_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,struct ddi_dma_attr * attr,size_t size)18716349Sqs148142 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
18727618SMichael.Speer@Sun.COM p_hxge_dma_common_t *dmap, struct ddi_dma_attr *attr, size_t size)
18736349Sqs148142 {
18746349Sqs148142 p_hxge_dma_common_t rx_dmap;
18756349Sqs148142 hxge_status_t status = HXGE_OK;
18766349Sqs148142
18776349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma"));
18786349Sqs148142
18796349Sqs148142 rx_dmap = (p_hxge_dma_common_t)
18806349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP);
18816349Sqs148142
18826349Sqs148142 rx_dmap->contig_alloc_type = B_FALSE;
18836349Sqs148142
18846349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
18857618SMichael.Speer@Sun.COM attr, size, &hxge_dev_desc_dma_acc_attr,
18866349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap);
18876349Sqs148142 if (status != HXGE_OK) {
18886349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
18896349Sqs148142 " hxge_alloc_rx_cntl_dma: Alloc Failed: "
18906349Sqs148142 " for size: %d", size));
18916349Sqs148142 goto hxge_alloc_rx_cntl_dma_fail1;
18926349Sqs148142 }
18936349Sqs148142
18946349Sqs148142 *dmap = rx_dmap;
18956349Sqs148142
18966349Sqs148142 goto hxge_alloc_rx_cntl_dma_exit;
18976349Sqs148142
18986349Sqs148142 hxge_alloc_rx_cntl_dma_fail1:
18996349Sqs148142 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t));
19006349Sqs148142
19016349Sqs148142 hxge_alloc_rx_cntl_dma_exit:
19026349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
19036349Sqs148142 "<== hxge_alloc_rx_cntl_dma status 0x%08x", status));
19046349Sqs148142
19056349Sqs148142 return (status);
19066349Sqs148142 }
19076349Sqs148142
19086349Sqs148142 /*ARGSUSED*/
19096349Sqs148142 static void
hxge_free_rx_cntl_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap)19106349Sqs148142 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
19116349Sqs148142 {
19126349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma"));
19136349Sqs148142
19146349Sqs148142 hxge_dma_mem_free(dmap);
19156349Sqs148142
19166349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma"));
19176349Sqs148142 }
19186349Sqs148142
19196349Sqs148142 static hxge_status_t
hxge_alloc_tx_mem_pool(p_hxge_t hxgep)19206349Sqs148142 hxge_alloc_tx_mem_pool(p_hxge_t hxgep)
19216349Sqs148142 {
19226349Sqs148142 hxge_status_t status = HXGE_OK;
19236349Sqs148142 int i, j;
19246349Sqs148142 uint32_t ndmas, st_tdc;
19256349Sqs148142 p_hxge_dma_pt_cfg_t p_all_cfgp;
19266349Sqs148142 p_hxge_hw_pt_cfg_t p_cfgp;
19276349Sqs148142 p_hxge_dma_pool_t dma_poolp;
19286349Sqs148142 p_hxge_dma_common_t *dma_buf_p;
19296349Sqs148142 p_hxge_dma_pool_t dma_cntl_poolp;
19306349Sqs148142 p_hxge_dma_common_t *dma_cntl_p;
19316349Sqs148142 size_t tx_buf_alloc_size;
19326349Sqs148142 size_t tx_cntl_alloc_size;
19336349Sqs148142 uint32_t *num_chunks; /* per dma */
19346349Sqs148142
19356349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool"));
19366349Sqs148142
19376349Sqs148142 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
19386349Sqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
19396349Sqs148142 st_tdc = p_cfgp->start_tdc;
19406349Sqs148142 ndmas = p_cfgp->max_tdcs;
19416349Sqs148142
19426349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: "
19436349Sqs148142 "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d",
19446349Sqs148142 p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs));
19456349Sqs148142 /*
19466349Sqs148142 * Allocate memory for each transmit DMA channel.
19476349Sqs148142 */
19486349Sqs148142 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
19496349Sqs148142 KM_SLEEP);
19506349Sqs148142 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
19516349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
19526349Sqs148142
19536349Sqs148142 dma_cntl_poolp = (p_hxge_dma_pool_t)
19546349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
19556349Sqs148142 dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
19566349Sqs148142 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
19576349Sqs148142
19586349Sqs148142 hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size;
19596349Sqs148142
19606349Sqs148142 /*
19616349Sqs148142 * Assume that each DMA channel will be configured with default
19626349Sqs148142 * transmit bufer size for copying transmit data. (For packet payload
19636349Sqs148142 * over this limit, packets will not be copied.)
19646349Sqs148142 */
19656349Sqs148142 tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size);
19666349Sqs148142
19676349Sqs148142 /*
19686349Sqs148142 * Addresses of transmit descriptor ring and the mailbox must be all
19696349Sqs148142 * cache-aligned (64 bytes).
19706349Sqs148142 */
19716349Sqs148142 tx_cntl_alloc_size = hxge_tx_ring_size;
19726349Sqs148142 tx_cntl_alloc_size *= (sizeof (tx_desc_t));
19736349Sqs148142 tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
19746349Sqs148142
19756349Sqs148142 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
19766349Sqs148142 KM_SLEEP);
19776349Sqs148142
19786349Sqs148142 /*
19796349Sqs148142 * Allocate memory for transmit buffers and descriptor rings. Replace
19806349Sqs148142 * allocation functions with interface functions provided by the
19816349Sqs148142 * partition manager when it is available.
19826349Sqs148142 *
19836349Sqs148142 * Allocate memory for the transmit buffer pool.
19846349Sqs148142 */
19856349Sqs148142 for (i = 0; i < ndmas; i++) {
19866349Sqs148142 num_chunks[i] = 0;
19876349Sqs148142 status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i],
19886349Sqs148142 tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]);
19896349Sqs148142 if (status != HXGE_OK) {
19906349Sqs148142 break;
19916349Sqs148142 }
19926349Sqs148142 st_tdc++;
19936349Sqs148142 }
19946349Sqs148142
19956349Sqs148142 if (i < ndmas) {
19966349Sqs148142 goto hxge_alloc_tx_mem_pool_fail1;
19976349Sqs148142 }
19986349Sqs148142
19996349Sqs148142 st_tdc = p_cfgp->start_tdc;
20006349Sqs148142
20016349Sqs148142 /*
20026349Sqs148142 * Allocate memory for descriptor rings and mailbox.
20036349Sqs148142 */
20046349Sqs148142 for (j = 0; j < ndmas; j++) {
20056349Sqs148142 status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j],
20066349Sqs148142 tx_cntl_alloc_size);
20076349Sqs148142 if (status != HXGE_OK) {
20086349Sqs148142 break;
20096349Sqs148142 }
20106349Sqs148142 st_tdc++;
20116349Sqs148142 }
20126349Sqs148142
20136349Sqs148142 if (j < ndmas) {
20146349Sqs148142 goto hxge_alloc_tx_mem_pool_fail2;
20156349Sqs148142 }
20166349Sqs148142
20176349Sqs148142 dma_poolp->ndmas = ndmas;
20186349Sqs148142 dma_poolp->num_chunks = num_chunks;
20196349Sqs148142 dma_poolp->buf_allocated = B_TRUE;
20206349Sqs148142 dma_poolp->dma_buf_pool_p = dma_buf_p;
20216349Sqs148142 hxgep->tx_buf_pool_p = dma_poolp;
20226349Sqs148142
20236349Sqs148142 dma_cntl_poolp->ndmas = ndmas;
20246349Sqs148142 dma_cntl_poolp->buf_allocated = B_TRUE;
20256349Sqs148142 dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
20266349Sqs148142 hxgep->tx_cntl_pool_p = dma_cntl_poolp;
20276349Sqs148142
20286349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL,
20296349Sqs148142 "==> hxge_alloc_tx_mem_pool: start_tdc %d "
20306349Sqs148142 "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas));
20316349Sqs148142
20326349Sqs148142 goto hxge_alloc_tx_mem_pool_exit;
20336349Sqs148142
20346349Sqs148142 hxge_alloc_tx_mem_pool_fail2:
20356349Sqs148142 /* Free control buffers */
20366349Sqs148142 j--;
20376349Sqs148142 for (; j >= 0; j--) {
20386349Sqs148142 hxge_free_tx_cntl_dma(hxgep,
20396349Sqs148142 (p_hxge_dma_common_t)dma_cntl_p[j]);
20406349Sqs148142 }
20416349Sqs148142
20426349Sqs148142 hxge_alloc_tx_mem_pool_fail1:
20436349Sqs148142 /* Free data buffers */
20446349Sqs148142 i--;
20456349Sqs148142 for (; i >= 0; i--) {
20466349Sqs148142 hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
20476349Sqs148142 num_chunks[i]);
20486349Sqs148142 }
20496349Sqs148142
20506349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
20516349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
20526349Sqs148142 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
20536349Sqs148142 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
20546349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
20556349Sqs148142
20566349Sqs148142 hxge_alloc_tx_mem_pool_exit:
20576349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL,
20586349Sqs148142 "<== hxge_alloc_tx_mem_pool:status 0x%08x", status));
20596349Sqs148142
20606349Sqs148142 return (status);
20616349Sqs148142 }
20626349Sqs148142
20636349Sqs148142 static hxge_status_t
hxge_alloc_tx_buf_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t alloc_size,size_t block_size,uint32_t * num_chunks)20646349Sqs148142 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
20656349Sqs148142 p_hxge_dma_common_t *dmap, size_t alloc_size,
20666349Sqs148142 size_t block_size, uint32_t *num_chunks)
20676349Sqs148142 {
20686349Sqs148142 p_hxge_dma_common_t tx_dmap;
20696349Sqs148142 hxge_status_t status = HXGE_OK;
20706349Sqs148142 size_t total_alloc_size;
20716349Sqs148142 size_t allocated = 0;
20726349Sqs148142 int i, size_index, array_size;
20736349Sqs148142
20746349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma"));
20756349Sqs148142
20766349Sqs148142 tx_dmap = (p_hxge_dma_common_t)
20776349Sqs148142 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
20786349Sqs148142
20796349Sqs148142 total_alloc_size = alloc_size;
20806349Sqs148142 i = 0;
20816349Sqs148142 size_index = 0;
20826349Sqs148142 array_size = sizeof (alloc_sizes) / sizeof (size_t);
20838141SMichael.Speer@Sun.COM while ((size_index < array_size) &&
20848141SMichael.Speer@Sun.COM (alloc_sizes[size_index] < alloc_size))
20856349Sqs148142 size_index++;
20866349Sqs148142 if (size_index >= array_size) {
20876349Sqs148142 size_index = array_size - 1;
20886349Sqs148142 }
20896349Sqs148142
20906349Sqs148142 while ((allocated < total_alloc_size) &&
20916349Sqs148142 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
20926349Sqs148142 tx_dmap[i].dma_chunk_index = i;
20936349Sqs148142 tx_dmap[i].block_size = block_size;
20946349Sqs148142 tx_dmap[i].alength = alloc_sizes[size_index];
20956349Sqs148142 tx_dmap[i].orig_alength = tx_dmap[i].alength;
20966349Sqs148142 tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
20976349Sqs148142 tx_dmap[i].dma_channel = dma_channel;
20986349Sqs148142 tx_dmap[i].contig_alloc_type = B_FALSE;
20996349Sqs148142
21006349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
21016349Sqs148142 &hxge_tx_dma_attr, tx_dmap[i].alength,
21026349Sqs148142 &hxge_dev_buf_dma_acc_attr,
21036349Sqs148142 DDI_DMA_WRITE | DDI_DMA_STREAMING,
21046349Sqs148142 (p_hxge_dma_common_t)(&tx_dmap[i]));
21056349Sqs148142 if (status != HXGE_OK) {
21066349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21076349Sqs148142 " hxge_alloc_tx_buf_dma: Alloc Failed: "
21086349Sqs148142 " for size: %d", alloc_sizes[size_index]));
21096349Sqs148142 size_index--;
21106349Sqs148142 } else {
21116349Sqs148142 i++;
21126349Sqs148142 allocated += alloc_sizes[size_index];
21136349Sqs148142 }
21146349Sqs148142 }
21156349Sqs148142
21166349Sqs148142 if (allocated < total_alloc_size) {
21176349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
21186349Sqs148142 " hxge_alloc_tx_buf_dma: failed due to"
21196349Sqs148142 " allocated(%d) < required(%d)",
21206349Sqs148142 allocated, total_alloc_size));
21216349Sqs148142 goto hxge_alloc_tx_mem_fail1;
21226349Sqs148142 }
21236349Sqs148142
21246349Sqs148142 *num_chunks = i;
21256349Sqs148142 *dmap = tx_dmap;
21266349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21276349Sqs148142 "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
21286349Sqs148142 *dmap, i));
21296349Sqs148142 goto hxge_alloc_tx_mem_exit;
21306349Sqs148142
21316349Sqs148142 hxge_alloc_tx_mem_fail1:
21326349Sqs148142 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
21336349Sqs148142
21346349Sqs148142 hxge_alloc_tx_mem_exit:
21356349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21366349Sqs148142 "<== hxge_alloc_tx_buf_dma status 0x%08x", status));
21376349Sqs148142
21386349Sqs148142 return (status);
21396349Sqs148142 }
21406349Sqs148142
21416349Sqs148142 /*ARGSUSED*/
21426349Sqs148142 static void
hxge_free_tx_buf_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap,uint32_t num_chunks)21436349Sqs148142 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
21446349Sqs148142 uint32_t num_chunks)
21456349Sqs148142 {
21466349Sqs148142 int i;
21476349Sqs148142
21486349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma"));
21496349Sqs148142
21506349Sqs148142 for (i = 0; i < num_chunks; i++) {
21516349Sqs148142 hxge_dma_mem_free(dmap++);
21526349Sqs148142 }
21536349Sqs148142
21546349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma"));
21556349Sqs148142 }
21566349Sqs148142
21576349Sqs148142 /*ARGSUSED*/
21586349Sqs148142 static hxge_status_t
hxge_alloc_tx_cntl_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t size)21596349Sqs148142 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
21606349Sqs148142 p_hxge_dma_common_t *dmap, size_t size)
21616349Sqs148142 {
21626349Sqs148142 p_hxge_dma_common_t tx_dmap;
21636349Sqs148142 hxge_status_t status = HXGE_OK;
21646349Sqs148142
21656349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma"));
21666349Sqs148142
21676349Sqs148142 tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t),
21686349Sqs148142 KM_SLEEP);
21696349Sqs148142
21706349Sqs148142 tx_dmap->contig_alloc_type = B_FALSE;
21716349Sqs148142
21726349Sqs148142 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
21737618SMichael.Speer@Sun.COM &hxge_tx_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
21746349Sqs148142 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap);
21756349Sqs148142 if (status != HXGE_OK) {
21766349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
21776349Sqs148142 " hxge_alloc_tx_cntl_dma: Alloc Failed: "
21786349Sqs148142 " for size: %d", size));
21796349Sqs148142 goto hxge_alloc_tx_cntl_dma_fail1;
21806349Sqs148142 }
21816349Sqs148142
21826349Sqs148142 *dmap = tx_dmap;
21836349Sqs148142
21846349Sqs148142 goto hxge_alloc_tx_cntl_dma_exit;
21856349Sqs148142
21866349Sqs148142 hxge_alloc_tx_cntl_dma_fail1:
21876349Sqs148142 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t));
21886349Sqs148142
21896349Sqs148142 hxge_alloc_tx_cntl_dma_exit:
21906349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21916349Sqs148142 "<== hxge_alloc_tx_cntl_dma status 0x%08x", status));
21926349Sqs148142
21936349Sqs148142 return (status);
21946349Sqs148142 }
21956349Sqs148142
21966349Sqs148142 /*ARGSUSED*/
21976349Sqs148142 static void
hxge_free_tx_cntl_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap)21986349Sqs148142 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
21996349Sqs148142 {
22006349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma"));
22016349Sqs148142
22026349Sqs148142 hxge_dma_mem_free(dmap);
22036349Sqs148142
22046349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma"));
22056349Sqs148142 }
22066349Sqs148142
22076349Sqs148142 static void
hxge_free_tx_mem_pool(p_hxge_t hxgep)22086349Sqs148142 hxge_free_tx_mem_pool(p_hxge_t hxgep)
22096349Sqs148142 {
22106349Sqs148142 uint32_t i, ndmas;
22116349Sqs148142 p_hxge_dma_pool_t dma_poolp;
22126349Sqs148142 p_hxge_dma_common_t *dma_buf_p;
22136349Sqs148142 p_hxge_dma_pool_t dma_cntl_poolp;
22146349Sqs148142 p_hxge_dma_common_t *dma_cntl_p;
22156349Sqs148142 uint32_t *num_chunks;
22166349Sqs148142
22176349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool"));
22186349Sqs148142
22196349Sqs148142 dma_poolp = hxgep->tx_buf_pool_p;
22206349Sqs148142 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
22216349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
22226349Sqs148142 "<== hxge_free_tx_mem_pool "
22236349Sqs148142 "(null rx buf pool or buf not allocated"));
22246349Sqs148142 return;
22256349Sqs148142 }
22266349Sqs148142
22276349Sqs148142 dma_cntl_poolp = hxgep->tx_cntl_pool_p;
22286349Sqs148142 if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
22296349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
22306349Sqs148142 "<== hxge_free_tx_mem_pool "
22316349Sqs148142 "(null tx cntl buf pool or cntl buf not allocated"));
22326349Sqs148142 return;
22336349Sqs148142 }
22346349Sqs148142
22356349Sqs148142 dma_buf_p = dma_poolp->dma_buf_pool_p;
22366349Sqs148142 num_chunks = dma_poolp->num_chunks;
22376349Sqs148142
22386349Sqs148142 dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
22396349Sqs148142 ndmas = dma_cntl_poolp->ndmas;
22406349Sqs148142
22416349Sqs148142 for (i = 0; i < ndmas; i++) {
22426349Sqs148142 hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
22436349Sqs148142 }
22446349Sqs148142
22456349Sqs148142 for (i = 0; i < ndmas; i++) {
22466349Sqs148142 hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]);
22476349Sqs148142 }
22486349Sqs148142
22496349Sqs148142 for (i = 0; i < ndmas; i++) {
22506349Sqs148142 KMEM_FREE(dma_buf_p[i],
22516349Sqs148142 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
22526349Sqs148142 KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
22536349Sqs148142 }
22546349Sqs148142
22556349Sqs148142 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
22566349Sqs148142 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
22576349Sqs148142 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
22586349Sqs148142 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
22596349Sqs148142 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
22606349Sqs148142
22616349Sqs148142 hxgep->tx_buf_pool_p = NULL;
22626349Sqs148142 hxgep->tx_cntl_pool_p = NULL;
22636349Sqs148142
22646349Sqs148142 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool"));
22656349Sqs148142 }
22666349Sqs148142
22676349Sqs148142 /*ARGSUSED*/
22686349Sqs148142 static hxge_status_t
hxge_dma_mem_alloc(p_hxge_t hxgep,dma_method_t method,struct ddi_dma_attr * dma_attrp,size_t length,ddi_device_acc_attr_t * acc_attr_p,uint_t xfer_flags,p_hxge_dma_common_t dma_p)22696349Sqs148142 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method,
22706349Sqs148142 struct ddi_dma_attr *dma_attrp,
22716349Sqs148142 size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
22726349Sqs148142 p_hxge_dma_common_t dma_p)
22736349Sqs148142 {
22746349Sqs148142 caddr_t kaddrp;
22756349Sqs148142 int ddi_status = DDI_SUCCESS;
22766349Sqs148142
22776349Sqs148142 dma_p->dma_handle = NULL;
22786349Sqs148142 dma_p->acc_handle = NULL;
22796349Sqs148142 dma_p->kaddrp = NULL;
22806349Sqs148142
22816349Sqs148142 ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp,
22826349Sqs148142 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
22836349Sqs148142 if (ddi_status != DDI_SUCCESS) {
22846349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
22856349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
22866349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
22876349Sqs148142 }
22886349Sqs148142
22896349Sqs148142 ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p,
22906349Sqs148142 xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
22916349Sqs148142 &dma_p->acc_handle);
22926349Sqs148142 if (ddi_status != DDI_SUCCESS) {
22936349Sqs148142 /* The caller will decide whether it is fatal */
22946349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
22956349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
22966349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle);
22976349Sqs148142 dma_p->dma_handle = NULL;
22986349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
22996349Sqs148142 }
23006349Sqs148142
23016349Sqs148142 if (dma_p->alength < length) {
23026349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23036349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length."));
23046349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle);
23056349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle);
23066349Sqs148142 dma_p->acc_handle = NULL;
23076349Sqs148142 dma_p->dma_handle = NULL;
23086349Sqs148142 return (HXGE_ERROR);
23096349Sqs148142 }
23106349Sqs148142
23116349Sqs148142 ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
23126349Sqs148142 kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
23136349Sqs148142 &dma_p->dma_cookie, &dma_p->ncookies);
23146349Sqs148142 if (ddi_status != DDI_DMA_MAPPED) {
23156349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23166349Sqs148142 "hxge_dma_mem_alloc:di_dma_addr_bind failed "
23176349Sqs148142 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
23186349Sqs148142 if (dma_p->acc_handle) {
23196349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle);
23206349Sqs148142 dma_p->acc_handle = NULL;
23216349Sqs148142 }
23226349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle);
23236349Sqs148142 dma_p->dma_handle = NULL;
23246349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
23256349Sqs148142 }
23266349Sqs148142
23276349Sqs148142 if (dma_p->ncookies != 1) {
23286349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL,
23296349Sqs148142 "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie"
23306349Sqs148142 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
23316349Sqs148142 if (dma_p->acc_handle) {
23326349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle);
23336349Sqs148142 dma_p->acc_handle = NULL;
23346349Sqs148142 }
23356349Sqs148142 (void) ddi_dma_unbind_handle(dma_p->dma_handle);
23366349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle);
23376349Sqs148142 dma_p->dma_handle = NULL;
23386349Sqs148142 return (HXGE_ERROR);
23396349Sqs148142 }
23406349Sqs148142
23416349Sqs148142 dma_p->kaddrp = kaddrp;
23426349Sqs148142 #if defined(__i386)
23436349Sqs148142 dma_p->ioaddr_pp =
23446349Sqs148142 (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
23456349Sqs148142 #else
23466349Sqs148142 dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress;
23476349Sqs148142 #endif
23486349Sqs148142
23496349Sqs148142 HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
23506349Sqs148142
23516349Sqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: "
23526349Sqs148142 "dma buffer allocated: dma_p $%p "
23536349Sqs148142 "return dmac_ladress from cookie $%p dmac_size %d "
23546349Sqs148142 "dma_p->ioaddr_p $%p "
23556349Sqs148142 "dma_p->orig_ioaddr_p $%p "
23566349Sqs148142 "orig_vatopa $%p "
23576349Sqs148142 "alength %d (0x%x) "
23586349Sqs148142 "kaddrp $%p "
23596349Sqs148142 "length %d (0x%x)",
23606349Sqs148142 dma_p,
23616349Sqs148142 dma_p->dma_cookie.dmac_laddress,
23626349Sqs148142 dma_p->dma_cookie.dmac_size,
23636349Sqs148142 dma_p->ioaddr_pp,
23646349Sqs148142 dma_p->orig_ioaddr_pp,
23656349Sqs148142 dma_p->orig_vatopa,
23666349Sqs148142 dma_p->alength, dma_p->alength,
23676349Sqs148142 kaddrp,
23686349Sqs148142 length, length));
23696349Sqs148142
23706349Sqs148142 return (HXGE_OK);
23716349Sqs148142 }
23726349Sqs148142
23736349Sqs148142 static void
hxge_dma_mem_free(p_hxge_dma_common_t dma_p)23746349Sqs148142 hxge_dma_mem_free(p_hxge_dma_common_t dma_p)
23756349Sqs148142 {
23767618SMichael.Speer@Sun.COM if (dma_p == NULL)
23777618SMichael.Speer@Sun.COM return;
23787618SMichael.Speer@Sun.COM
23796349Sqs148142 if (dma_p->dma_handle != NULL) {
23806349Sqs148142 if (dma_p->ncookies) {
23816349Sqs148142 (void) ddi_dma_unbind_handle(dma_p->dma_handle);
23826349Sqs148142 dma_p->ncookies = 0;
23836349Sqs148142 }
23846349Sqs148142 ddi_dma_free_handle(&dma_p->dma_handle);
23856349Sqs148142 dma_p->dma_handle = NULL;
23866349Sqs148142 }
23877618SMichael.Speer@Sun.COM
23886349Sqs148142 if (dma_p->acc_handle != NULL) {
23896349Sqs148142 ddi_dma_mem_free(&dma_p->acc_handle);
23906349Sqs148142 dma_p->acc_handle = NULL;
23916349Sqs148142 HPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
23926349Sqs148142 }
23937618SMichael.Speer@Sun.COM
23946349Sqs148142 dma_p->kaddrp = NULL;
23956349Sqs148142 dma_p->alength = NULL;
23966349Sqs148142 }
23976349Sqs148142
23986349Sqs148142 /*
23996349Sqs148142 * hxge_m_start() -- start transmitting and receiving.
24006349Sqs148142 *
24016349Sqs148142 * This function is called by the MAC layer when the first
24026349Sqs148142 * stream is open to prepare the hardware ready for sending
24036349Sqs148142 * and transmitting packets.
24046349Sqs148142 */
24056349Sqs148142 static int
hxge_m_start(void * arg)24066349Sqs148142 hxge_m_start(void *arg)
24076349Sqs148142 {
24086349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg;
24096349Sqs148142
24106349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start"));
24116349Sqs148142
24126349Sqs148142 MUTEX_ENTER(hxgep->genlock);
24136349Sqs148142
24146349Sqs148142 if (hxge_init(hxgep) != DDI_SUCCESS) {
24156349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24166349Sqs148142 "<== hxge_m_start: initialization failed"));
24176349Sqs148142 MUTEX_EXIT(hxgep->genlock);
24186349Sqs148142 return (EIO);
24196349Sqs148142 }
24206349Sqs148142
24216349Sqs148142 if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) {
24226349Sqs148142 /*
24236349Sqs148142 * Start timer to check the system error and tx hangs
24246349Sqs148142 */
24256349Sqs148142 hxgep->hxge_timerid = hxge_start_timer(hxgep,
24266349Sqs148142 hxge_check_hw_state, HXGE_CHECK_TIMER);
24276349Sqs148142
24286349Sqs148142 hxgep->hxge_mac_state = HXGE_MAC_STARTED;
24297949SQiyan.Sun@Sun.COM
24307949SQiyan.Sun@Sun.COM hxgep->timeout.link_status = 0;
24317949SQiyan.Sun@Sun.COM hxgep->timeout.report_link_status = B_TRUE;
24327949SQiyan.Sun@Sun.COM hxgep->timeout.ticks = drv_usectohz(2 * 1000000);
24337949SQiyan.Sun@Sun.COM
24347949SQiyan.Sun@Sun.COM /* Start the link status timer to check the link status */
24357949SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock);
24367949SQiyan.Sun@Sun.COM hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
24377949SQiyan.Sun@Sun.COM hxgep->timeout.ticks);
24387949SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock);
24396349Sqs148142 }
24406349Sqs148142
24416349Sqs148142 MUTEX_EXIT(hxgep->genlock);
24426349Sqs148142
24436349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start"));
24446349Sqs148142
24456349Sqs148142 return (0);
24466349Sqs148142 }
24476349Sqs148142
24486349Sqs148142 /*
24496349Sqs148142 * hxge_m_stop(): stop transmitting and receiving.
24506349Sqs148142 */
24516349Sqs148142 static void
hxge_m_stop(void * arg)24526349Sqs148142 hxge_m_stop(void *arg)
24536349Sqs148142 {
24546349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg;
24556349Sqs148142
24566349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop"));
24576349Sqs148142
24586349Sqs148142 if (hxgep->hxge_timerid) {
24596349Sqs148142 hxge_stop_timer(hxgep, hxgep->hxge_timerid);
24606349Sqs148142 hxgep->hxge_timerid = 0;
24616349Sqs148142 }
24626349Sqs148142
24637949SQiyan.Sun@Sun.COM /* Stop the link status timer before unregistering */
24647949SQiyan.Sun@Sun.COM MUTEX_ENTER(&hxgep->timeout.lock);
24657949SQiyan.Sun@Sun.COM if (hxgep->timeout.id) {
24667949SQiyan.Sun@Sun.COM (void) untimeout(hxgep->timeout.id);
24677949SQiyan.Sun@Sun.COM hxgep->timeout.id = 0;
24687949SQiyan.Sun@Sun.COM }
24697949SQiyan.Sun@Sun.COM hxge_link_update(hxgep, LINK_STATE_DOWN);
24707949SQiyan.Sun@Sun.COM MUTEX_EXIT(&hxgep->timeout.lock);
24717949SQiyan.Sun@Sun.COM
24726349Sqs148142 MUTEX_ENTER(hxgep->genlock);
24736349Sqs148142
24746349Sqs148142 hxge_uninit(hxgep);
24756349Sqs148142
24766349Sqs148142 hxgep->hxge_mac_state = HXGE_MAC_STOPPED;
24776349Sqs148142
24786349Sqs148142 MUTEX_EXIT(hxgep->genlock);
24796349Sqs148142
24806349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop"));
24816349Sqs148142 }
24826349Sqs148142
24836349Sqs148142 static int
hxge_m_multicst(void * arg,boolean_t add,const uint8_t * mca)24846349Sqs148142 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
24856349Sqs148142 {
24866349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg;
24876349Sqs148142 struct ether_addr addrp;
24886349Sqs148142
24896349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add));
24906349Sqs148142
24916349Sqs148142 bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
24926349Sqs148142
24936349Sqs148142 if (add) {
24946349Sqs148142 if (hxge_add_mcast_addr(hxgep, &addrp)) {
24956349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24966349Sqs148142 "<== hxge_m_multicst: add multicast failed"));
24976349Sqs148142 return (EINVAL);
24986349Sqs148142 }
24996349Sqs148142 } else {
25006349Sqs148142 if (hxge_del_mcast_addr(hxgep, &addrp)) {
25016349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25026349Sqs148142 "<== hxge_m_multicst: del multicast failed"));
25036349Sqs148142 return (EINVAL);
25046349Sqs148142 }
25056349Sqs148142 }
25066349Sqs148142
25076349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst"));
25086349Sqs148142
25096349Sqs148142 return (0);
25106349Sqs148142 }
25116349Sqs148142
25126349Sqs148142 static int
hxge_m_promisc(void * arg,boolean_t on)25136349Sqs148142 hxge_m_promisc(void *arg, boolean_t on)
25146349Sqs148142 {
25156349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg;
25166349Sqs148142
25176349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on));
25186349Sqs148142
25196349Sqs148142 if (hxge_set_promisc(hxgep, on)) {
25206349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25216349Sqs148142 "<== hxge_m_promisc: set promisc failed"));
25226349Sqs148142 return (EINVAL);
25236349Sqs148142 }
25246349Sqs148142
25256349Sqs148142 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on));
25266349Sqs148142
25276349Sqs148142 return (0);
25286349Sqs148142 }
25296349Sqs148142
25306349Sqs148142 static void
hxge_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)25316349Sqs148142 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
25326349Sqs148142 {
25336349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg;
25346349Sqs148142 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
25356349Sqs148142 boolean_t need_privilege;
25366349Sqs148142 int err;
25376349Sqs148142 int cmd;
25386349Sqs148142
25396349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl"));
25406349Sqs148142
25416349Sqs148142 iocp = (struct iocblk *)mp->b_rptr;
25426349Sqs148142 iocp->ioc_error = 0;
25436349Sqs148142 need_privilege = B_TRUE;
25446349Sqs148142 cmd = iocp->ioc_cmd;
25456349Sqs148142
25466349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd));
25476349Sqs148142 switch (cmd) {
25486349Sqs148142 default:
25496349Sqs148142 miocnak(wq, mp, 0, EINVAL);
25506349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid"));
25516349Sqs148142 return;
25526349Sqs148142
25536349Sqs148142 case LB_GET_INFO_SIZE:
25546349Sqs148142 case LB_GET_INFO:
25556349Sqs148142 case LB_GET_MODE:
25566349Sqs148142 need_privilege = B_FALSE;
25576349Sqs148142 break;
25586349Sqs148142
25596349Sqs148142 case LB_SET_MODE:
25606349Sqs148142 break;
25616349Sqs148142
25626349Sqs148142 case ND_GET:
25636349Sqs148142 need_privilege = B_FALSE;
25646349Sqs148142 break;
25656349Sqs148142 case ND_SET:
25666349Sqs148142 break;
25676349Sqs148142
25686349Sqs148142 case HXGE_GET_TX_RING_SZ:
25696349Sqs148142 case HXGE_GET_TX_DESC:
25706349Sqs148142 case HXGE_TX_SIDE_RESET:
25716349Sqs148142 case HXGE_RX_SIDE_RESET:
25726349Sqs148142 case HXGE_GLOBAL_RESET:
25736349Sqs148142 case HXGE_RESET_MAC:
25746349Sqs148142 case HXGE_PUT_TCAM:
25756349Sqs148142 case HXGE_GET_TCAM:
25766349Sqs148142 case HXGE_RTRACE:
25776349Sqs148142
25786349Sqs148142 need_privilege = B_FALSE;
25796349Sqs148142 break;
25806349Sqs148142 }
25816349Sqs148142
25826349Sqs148142 if (need_privilege) {
25836349Sqs148142 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
25846349Sqs148142 if (err != 0) {
25856349Sqs148142 miocnak(wq, mp, 0, err);
25866349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25876349Sqs148142 "<== hxge_m_ioctl: no priv"));
25886349Sqs148142 return;
25896349Sqs148142 }
25906349Sqs148142 }
25916349Sqs148142
25926349Sqs148142 switch (cmd) {
25936349Sqs148142 case ND_GET:
25946349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command"));
25956349Sqs148142 case ND_SET:
25966349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command"));
25976349Sqs148142 hxge_param_ioctl(hxgep, wq, mp, iocp);
25986349Sqs148142 break;
25996349Sqs148142
26006349Sqs148142 case LB_GET_MODE:
26016349Sqs148142 case LB_SET_MODE:
26026349Sqs148142 case LB_GET_INFO_SIZE:
26036349Sqs148142 case LB_GET_INFO:
26046349Sqs148142 hxge_loopback_ioctl(hxgep, wq, mp, iocp);
26056349Sqs148142 break;
26066349Sqs148142
26076349Sqs148142 case HXGE_PUT_TCAM:
26086349Sqs148142 case HXGE_GET_TCAM:
26096349Sqs148142 case HXGE_GET_TX_RING_SZ:
26106349Sqs148142 case HXGE_GET_TX_DESC:
26116349Sqs148142 case HXGE_TX_SIDE_RESET:
26126349Sqs148142 case HXGE_RX_SIDE_RESET:
26136349Sqs148142 case HXGE_GLOBAL_RESET:
26146349Sqs148142 case HXGE_RESET_MAC:
26156349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL,
26166349Sqs148142 "==> hxge_m_ioctl: cmd 0x%x", cmd));
26176349Sqs148142 hxge_hw_ioctl(hxgep, wq, mp, iocp);
26186349Sqs148142 break;
26196349Sqs148142 }
26206349Sqs148142
26216349Sqs148142 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl"));
26226349Sqs148142 }
26236349Sqs148142
26246349Sqs148142 /*ARGSUSED*/
26258718SMichael.Speer@Sun.COM static int
hxge_tx_ring_start(mac_ring_driver_t rdriver,uint64_t mr_gen_num)26268718SMichael.Speer@Sun.COM hxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
26278718SMichael.Speer@Sun.COM {
26288718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver;
26298718SMichael.Speer@Sun.COM p_hxge_t hxgep;
26308718SMichael.Speer@Sun.COM p_tx_ring_t ring;
26318718SMichael.Speer@Sun.COM
26328718SMichael.Speer@Sun.COM ASSERT(rhp != NULL);
26338718SMichael.Speer@Sun.COM ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26348718SMichael.Speer@Sun.COM
26358718SMichael.Speer@Sun.COM hxgep = rhp->hxgep;
26368718SMichael.Speer@Sun.COM
26378718SMichael.Speer@Sun.COM /*
26388718SMichael.Speer@Sun.COM * Get the ring pointer.
26398718SMichael.Speer@Sun.COM */
26408718SMichael.Speer@Sun.COM ring = hxgep->tx_rings->rings[rhp->index];
26418718SMichael.Speer@Sun.COM
26428718SMichael.Speer@Sun.COM /*
26438718SMichael.Speer@Sun.COM * Fill in the handle for the transmit.
26448718SMichael.Speer@Sun.COM */
26458718SMichael.Speer@Sun.COM MUTEX_ENTER(&ring->lock);
264610091SMichael.Speer@Sun.COM rhp->started = B_TRUE;
26478718SMichael.Speer@Sun.COM ring->ring_handle = rhp->ring_handle;
26488718SMichael.Speer@Sun.COM MUTEX_EXIT(&ring->lock);
26498718SMichael.Speer@Sun.COM
26508718SMichael.Speer@Sun.COM return (0);
26518718SMichael.Speer@Sun.COM }
26528718SMichael.Speer@Sun.COM
26538718SMichael.Speer@Sun.COM static void
hxge_tx_ring_stop(mac_ring_driver_t rdriver)26548718SMichael.Speer@Sun.COM hxge_tx_ring_stop(mac_ring_driver_t rdriver)
26558718SMichael.Speer@Sun.COM {
26568718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver;
26578718SMichael.Speer@Sun.COM p_hxge_t hxgep;
26588718SMichael.Speer@Sun.COM p_tx_ring_t ring;
26598718SMichael.Speer@Sun.COM
26608718SMichael.Speer@Sun.COM ASSERT(rhp != NULL);
26618718SMichael.Speer@Sun.COM ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26628718SMichael.Speer@Sun.COM
26638718SMichael.Speer@Sun.COM hxgep = rhp->hxgep;
26648718SMichael.Speer@Sun.COM ring = hxgep->tx_rings->rings[rhp->index];
26658718SMichael.Speer@Sun.COM
26668718SMichael.Speer@Sun.COM MUTEX_ENTER(&ring->lock);
26678718SMichael.Speer@Sun.COM ring->ring_handle = (mac_ring_handle_t)NULL;
266810091SMichael.Speer@Sun.COM rhp->started = B_FALSE;
26698718SMichael.Speer@Sun.COM MUTEX_EXIT(&ring->lock);
26708718SMichael.Speer@Sun.COM }
26718718SMichael.Speer@Sun.COM
26728718SMichael.Speer@Sun.COM static int
hxge_rx_ring_start(mac_ring_driver_t rdriver,uint64_t mr_gen_num)26738718SMichael.Speer@Sun.COM hxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
26748718SMichael.Speer@Sun.COM {
26758718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver;
26768718SMichael.Speer@Sun.COM p_hxge_t hxgep;
26778718SMichael.Speer@Sun.COM p_rx_rcr_ring_t ring;
26788718SMichael.Speer@Sun.COM int i;
26798718SMichael.Speer@Sun.COM
26808718SMichael.Speer@Sun.COM ASSERT(rhp != NULL);
26818718SMichael.Speer@Sun.COM ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26828718SMichael.Speer@Sun.COM
26838718SMichael.Speer@Sun.COM hxgep = rhp->hxgep;
26848718SMichael.Speer@Sun.COM
26858718SMichael.Speer@Sun.COM /*
26868718SMichael.Speer@Sun.COM * Get pointer to ring.
26878718SMichael.Speer@Sun.COM */
26888718SMichael.Speer@Sun.COM ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index];
26898718SMichael.Speer@Sun.COM
26908718SMichael.Speer@Sun.COM MUTEX_ENTER(&ring->lock);
26918718SMichael.Speer@Sun.COM
26928718SMichael.Speer@Sun.COM if (rhp->started) {
26938718SMichael.Speer@Sun.COM MUTEX_EXIT(&ring->lock);
26948718SMichael.Speer@Sun.COM return (0);
26958718SMichael.Speer@Sun.COM }
26968718SMichael.Speer@Sun.COM
26978718SMichael.Speer@Sun.COM /*
26988718SMichael.Speer@Sun.COM * Set the ldvp and ldgp pointers to enable/disable
26998718SMichael.Speer@Sun.COM * polling.
27008718SMichael.Speer@Sun.COM */
27018718SMichael.Speer@Sun.COM for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
27028718SMichael.Speer@Sun.COM if ((hxgep->ldgvp->ldvp[i].is_rxdma == 1) &&
27038718SMichael.Speer@Sun.COM (hxgep->ldgvp->ldvp[i].channel == rhp->index)) {
27048718SMichael.Speer@Sun.COM ring->ldvp = &hxgep->ldgvp->ldvp[i];
27058718SMichael.Speer@Sun.COM ring->ldgp = hxgep->ldgvp->ldvp[i].ldgp;
27068718SMichael.Speer@Sun.COM break;
27078718SMichael.Speer@Sun.COM }
27088718SMichael.Speer@Sun.COM }
27098718SMichael.Speer@Sun.COM
27108718SMichael.Speer@Sun.COM rhp->started = B_TRUE;
27118718SMichael.Speer@Sun.COM ring->rcr_mac_handle = rhp->ring_handle;
27128718SMichael.Speer@Sun.COM ring->rcr_gen_num = mr_gen_num;
27138718SMichael.Speer@Sun.COM MUTEX_EXIT(&ring->lock);
27148718SMichael.Speer@Sun.COM
27158718SMichael.Speer@Sun.COM return (0);
27168718SMichael.Speer@Sun.COM }
27178718SMichael.Speer@Sun.COM
27188718SMichael.Speer@Sun.COM static void
hxge_rx_ring_stop(mac_ring_driver_t rdriver)27198718SMichael.Speer@Sun.COM hxge_rx_ring_stop(mac_ring_driver_t rdriver)
27208718SMichael.Speer@Sun.COM {
27218718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver;
27228718SMichael.Speer@Sun.COM p_hxge_t hxgep;
27238718SMichael.Speer@Sun.COM p_rx_rcr_ring_t ring;
27248718SMichael.Speer@Sun.COM
27258718SMichael.Speer@Sun.COM ASSERT(rhp != NULL);
27268718SMichael.Speer@Sun.COM ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
27278718SMichael.Speer@Sun.COM
27288718SMichael.Speer@Sun.COM hxgep = rhp->hxgep;
27298718SMichael.Speer@Sun.COM ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index];
27308718SMichael.Speer@Sun.COM
27318718SMichael.Speer@Sun.COM MUTEX_ENTER(&ring->lock);
27328718SMichael.Speer@Sun.COM rhp->started = B_TRUE;
27338718SMichael.Speer@Sun.COM ring->rcr_mac_handle = NULL;
27348718SMichael.Speer@Sun.COM ring->ldvp = NULL;
27358718SMichael.Speer@Sun.COM ring->ldgp = NULL;
27368718SMichael.Speer@Sun.COM MUTEX_EXIT(&ring->lock);
27378718SMichael.Speer@Sun.COM }
27388718SMichael.Speer@Sun.COM
27398718SMichael.Speer@Sun.COM static int
hxge_rx_group_start(mac_group_driver_t gdriver)27408718SMichael.Speer@Sun.COM hxge_rx_group_start(mac_group_driver_t gdriver)
27418718SMichael.Speer@Sun.COM {
27428718SMichael.Speer@Sun.COM hxge_ring_group_t *group = (hxge_ring_group_t *)gdriver;
27438718SMichael.Speer@Sun.COM
27448718SMichael.Speer@Sun.COM ASSERT(group->hxgep != NULL);
27458718SMichael.Speer@Sun.COM ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
27468718SMichael.Speer@Sun.COM
27478718SMichael.Speer@Sun.COM MUTEX_ENTER(group->hxgep->genlock);
27488718SMichael.Speer@Sun.COM group->started = B_TRUE;
27498718SMichael.Speer@Sun.COM MUTEX_EXIT(group->hxgep->genlock);
27508718SMichael.Speer@Sun.COM
27518718SMichael.Speer@Sun.COM return (0);
27528718SMichael.Speer@Sun.COM }
27538718SMichael.Speer@Sun.COM
27548718SMichael.Speer@Sun.COM static void
hxge_rx_group_stop(mac_group_driver_t gdriver)27558718SMichael.Speer@Sun.COM hxge_rx_group_stop(mac_group_driver_t gdriver)
27568718SMichael.Speer@Sun.COM {
27578718SMichael.Speer@Sun.COM hxge_ring_group_t *group = (hxge_ring_group_t *)gdriver;
27588718SMichael.Speer@Sun.COM
27598718SMichael.Speer@Sun.COM ASSERT(group->hxgep != NULL);
27608718SMichael.Speer@Sun.COM ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
27618718SMichael.Speer@Sun.COM ASSERT(group->started == B_TRUE);
27628718SMichael.Speer@Sun.COM
27638718SMichael.Speer@Sun.COM MUTEX_ENTER(group->hxgep->genlock);
27648718SMichael.Speer@Sun.COM group->started = B_FALSE;
27658718SMichael.Speer@Sun.COM MUTEX_EXIT(group->hxgep->genlock);
27668718SMichael.Speer@Sun.COM }
27678718SMichael.Speer@Sun.COM
27688718SMichael.Speer@Sun.COM static int
hxge_mmac_get_slot(p_hxge_t hxgep,int * slot)27698718SMichael.Speer@Sun.COM hxge_mmac_get_slot(p_hxge_t hxgep, int *slot)
27708718SMichael.Speer@Sun.COM {
27718718SMichael.Speer@Sun.COM int i;
27728718SMichael.Speer@Sun.COM
27738718SMichael.Speer@Sun.COM /*
27748718SMichael.Speer@Sun.COM * Find an open slot.
27758718SMichael.Speer@Sun.COM */
27768718SMichael.Speer@Sun.COM for (i = 0; i < hxgep->mmac.total; i++) {
27778718SMichael.Speer@Sun.COM if (!hxgep->mmac.addrs[i].set) {
27788718SMichael.Speer@Sun.COM *slot = i;
27798718SMichael.Speer@Sun.COM return (0);
27808718SMichael.Speer@Sun.COM }
27818718SMichael.Speer@Sun.COM }
27828718SMichael.Speer@Sun.COM
27838718SMichael.Speer@Sun.COM return (ENXIO);
27848718SMichael.Speer@Sun.COM }
27858718SMichael.Speer@Sun.COM
27868718SMichael.Speer@Sun.COM static int
hxge_mmac_set_addr(p_hxge_t hxgep,int slot,const uint8_t * addr)27878718SMichael.Speer@Sun.COM hxge_mmac_set_addr(p_hxge_t hxgep, int slot, const uint8_t *addr)
27888718SMichael.Speer@Sun.COM {
27898718SMichael.Speer@Sun.COM struct ether_addr eaddr;
27908718SMichael.Speer@Sun.COM hxge_status_t status = HXGE_OK;
27918718SMichael.Speer@Sun.COM
27928718SMichael.Speer@Sun.COM bcopy(addr, (uint8_t *)&eaddr, ETHERADDRL);
27938718SMichael.Speer@Sun.COM
27948718SMichael.Speer@Sun.COM /*
27958718SMichael.Speer@Sun.COM * Set new interface local address and re-init device.
27968718SMichael.Speer@Sun.COM * This is destructive to any other streams attached
27978718SMichael.Speer@Sun.COM * to this device.
27988718SMichael.Speer@Sun.COM */
27998718SMichael.Speer@Sun.COM RW_ENTER_WRITER(&hxgep->filter_lock);
28008718SMichael.Speer@Sun.COM status = hxge_pfc_set_mac_address(hxgep, slot, &eaddr);
28018718SMichael.Speer@Sun.COM RW_EXIT(&hxgep->filter_lock);
28028718SMichael.Speer@Sun.COM if (status != HXGE_OK)
28038718SMichael.Speer@Sun.COM return (status);
28048718SMichael.Speer@Sun.COM
28058718SMichael.Speer@Sun.COM hxgep->mmac.addrs[slot].set = B_TRUE;
28068718SMichael.Speer@Sun.COM bcopy(addr, hxgep->mmac.addrs[slot].addr, ETHERADDRL);
28078718SMichael.Speer@Sun.COM hxgep->mmac.available--;
28088718SMichael.Speer@Sun.COM if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
28098718SMichael.Speer@Sun.COM hxgep->mmac.addrs[slot].primary = B_TRUE;
28108718SMichael.Speer@Sun.COM
28118718SMichael.Speer@Sun.COM return (0);
28128718SMichael.Speer@Sun.COM }
28138718SMichael.Speer@Sun.COM
28148718SMichael.Speer@Sun.COM static int
hxge_mmac_find_addr(p_hxge_t hxgep,const uint8_t * addr,int * slot)28158718SMichael.Speer@Sun.COM hxge_mmac_find_addr(p_hxge_t hxgep, const uint8_t *addr, int *slot)
28168718SMichael.Speer@Sun.COM {
28178718SMichael.Speer@Sun.COM int i, result;
28188718SMichael.Speer@Sun.COM
28198718SMichael.Speer@Sun.COM for (i = 0; i < hxgep->mmac.total; i++) {
28208718SMichael.Speer@Sun.COM if (hxgep->mmac.addrs[i].set) {
28218718SMichael.Speer@Sun.COM result = memcmp(hxgep->mmac.addrs[i].addr,
28228718SMichael.Speer@Sun.COM addr, ETHERADDRL);
28238718SMichael.Speer@Sun.COM if (result == 0) {
28248718SMichael.Speer@Sun.COM *slot = i;
28258718SMichael.Speer@Sun.COM return (0);
28268718SMichael.Speer@Sun.COM }
28278718SMichael.Speer@Sun.COM }
28288718SMichael.Speer@Sun.COM }
28298718SMichael.Speer@Sun.COM
28308718SMichael.Speer@Sun.COM return (EINVAL);
28318718SMichael.Speer@Sun.COM }
28328718SMichael.Speer@Sun.COM
28338718SMichael.Speer@Sun.COM static int
hxge_mmac_unset_addr(p_hxge_t hxgep,int slot)28348718SMichael.Speer@Sun.COM hxge_mmac_unset_addr(p_hxge_t hxgep, int slot)
28358718SMichael.Speer@Sun.COM {
28368718SMichael.Speer@Sun.COM hxge_status_t status;
28378718SMichael.Speer@Sun.COM int i;
28388718SMichael.Speer@Sun.COM
28398718SMichael.Speer@Sun.COM status = hxge_pfc_clear_mac_address(hxgep, slot);
28408718SMichael.Speer@Sun.COM if (status != HXGE_OK)
28418718SMichael.Speer@Sun.COM return (status);
28428718SMichael.Speer@Sun.COM
28438718SMichael.Speer@Sun.COM for (i = 0; i < ETHERADDRL; i++)
28448718SMichael.Speer@Sun.COM hxgep->mmac.addrs[slot].addr[i] = 0;
28458718SMichael.Speer@Sun.COM
28468718SMichael.Speer@Sun.COM hxgep->mmac.addrs[slot].set = B_FALSE;
28478718SMichael.Speer@Sun.COM if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
28488718SMichael.Speer@Sun.COM hxgep->mmac.addrs[slot].primary = B_FALSE;
28498718SMichael.Speer@Sun.COM hxgep->mmac.available++;
28508718SMichael.Speer@Sun.COM
28518718SMichael.Speer@Sun.COM return (0);
28528718SMichael.Speer@Sun.COM }
28538718SMichael.Speer@Sun.COM
28548718SMichael.Speer@Sun.COM static int
hxge_rx_group_add_mac(void * arg,const uint8_t * mac_addr)28558718SMichael.Speer@Sun.COM hxge_rx_group_add_mac(void *arg, const uint8_t *mac_addr)
28568718SMichael.Speer@Sun.COM {
28578718SMichael.Speer@Sun.COM hxge_ring_group_t *group = arg;
28588718SMichael.Speer@Sun.COM p_hxge_t hxgep = group->hxgep;
28598718SMichael.Speer@Sun.COM int slot = 0;
28608718SMichael.Speer@Sun.COM
28618718SMichael.Speer@Sun.COM ASSERT(group->type == MAC_RING_TYPE_RX);
28628718SMichael.Speer@Sun.COM
28638718SMichael.Speer@Sun.COM MUTEX_ENTER(hxgep->genlock);
28648718SMichael.Speer@Sun.COM
28658718SMichael.Speer@Sun.COM /*
28668718SMichael.Speer@Sun.COM * Find a slot for the address.
28678718SMichael.Speer@Sun.COM */
28688718SMichael.Speer@Sun.COM if (hxge_mmac_get_slot(hxgep, &slot) != 0) {
28698718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
28708718SMichael.Speer@Sun.COM return (ENOSPC);
28718718SMichael.Speer@Sun.COM }
28728718SMichael.Speer@Sun.COM
28738718SMichael.Speer@Sun.COM /*
28748718SMichael.Speer@Sun.COM * Program the MAC address.
28758718SMichael.Speer@Sun.COM */
28768718SMichael.Speer@Sun.COM if (hxge_mmac_set_addr(hxgep, slot, mac_addr) != 0) {
28778718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
28788718SMichael.Speer@Sun.COM return (ENOSPC);
28798718SMichael.Speer@Sun.COM }
28808718SMichael.Speer@Sun.COM
28818718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
28828718SMichael.Speer@Sun.COM return (0);
28838718SMichael.Speer@Sun.COM }
28848718SMichael.Speer@Sun.COM
28858718SMichael.Speer@Sun.COM static int
hxge_rx_group_rem_mac(void * arg,const uint8_t * mac_addr)28868718SMichael.Speer@Sun.COM hxge_rx_group_rem_mac(void *arg, const uint8_t *mac_addr)
28878718SMichael.Speer@Sun.COM {
28888718SMichael.Speer@Sun.COM hxge_ring_group_t *group = arg;
28898718SMichael.Speer@Sun.COM p_hxge_t hxgep = group->hxgep;
28908718SMichael.Speer@Sun.COM int rv, slot;
28918718SMichael.Speer@Sun.COM
28928718SMichael.Speer@Sun.COM ASSERT(group->type == MAC_RING_TYPE_RX);
28938718SMichael.Speer@Sun.COM
28948718SMichael.Speer@Sun.COM MUTEX_ENTER(hxgep->genlock);
28958718SMichael.Speer@Sun.COM
28968718SMichael.Speer@Sun.COM if ((rv = hxge_mmac_find_addr(hxgep, mac_addr, &slot)) != 0) {
28978718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
28988718SMichael.Speer@Sun.COM return (rv);
28998718SMichael.Speer@Sun.COM }
29008718SMichael.Speer@Sun.COM
29018718SMichael.Speer@Sun.COM if ((rv = hxge_mmac_unset_addr(hxgep, slot)) != 0) {
29028718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
29038718SMichael.Speer@Sun.COM return (rv);
29048718SMichael.Speer@Sun.COM }
29058718SMichael.Speer@Sun.COM
29068718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
29078718SMichael.Speer@Sun.COM return (0);
29088718SMichael.Speer@Sun.COM }
29098718SMichael.Speer@Sun.COM
29108718SMichael.Speer@Sun.COM static void
hxge_group_get(void * arg,mac_ring_type_t type,int groupid,mac_group_info_t * infop,mac_group_handle_t gh)29118718SMichael.Speer@Sun.COM hxge_group_get(void *arg, mac_ring_type_t type, int groupid,
29128718SMichael.Speer@Sun.COM mac_group_info_t *infop, mac_group_handle_t gh)
29138718SMichael.Speer@Sun.COM {
29148718SMichael.Speer@Sun.COM p_hxge_t hxgep = arg;
29158718SMichael.Speer@Sun.COM hxge_ring_group_t *group;
29168718SMichael.Speer@Sun.COM
29178718SMichael.Speer@Sun.COM ASSERT(type == MAC_RING_TYPE_RX);
29188718SMichael.Speer@Sun.COM
29198718SMichael.Speer@Sun.COM switch (type) {
29208718SMichael.Speer@Sun.COM case MAC_RING_TYPE_RX:
29218718SMichael.Speer@Sun.COM group = &hxgep->rx_groups[groupid];
29228718SMichael.Speer@Sun.COM group->hxgep = hxgep;
29238718SMichael.Speer@Sun.COM group->ghandle = gh;
29248718SMichael.Speer@Sun.COM group->index = groupid;
29258718SMichael.Speer@Sun.COM group->type = type;
29268718SMichael.Speer@Sun.COM
29278718SMichael.Speer@Sun.COM infop->mgi_driver = (mac_group_driver_t)group;
29288718SMichael.Speer@Sun.COM infop->mgi_start = hxge_rx_group_start;
29298718SMichael.Speer@Sun.COM infop->mgi_stop = hxge_rx_group_stop;
29308718SMichael.Speer@Sun.COM infop->mgi_addmac = hxge_rx_group_add_mac;
29318718SMichael.Speer@Sun.COM infop->mgi_remmac = hxge_rx_group_rem_mac;
29328718SMichael.Speer@Sun.COM infop->mgi_count = HXGE_MAX_RDCS;
29338718SMichael.Speer@Sun.COM break;
29348718SMichael.Speer@Sun.COM
29358718SMichael.Speer@Sun.COM case MAC_RING_TYPE_TX:
29368718SMichael.Speer@Sun.COM default:
29378718SMichael.Speer@Sun.COM break;
29388718SMichael.Speer@Sun.COM }
29398718SMichael.Speer@Sun.COM }
29408718SMichael.Speer@Sun.COM
2941*11878SVenu.Iyer@Sun.COM static int
hxge_ring_get_htable_idx(p_hxge_t hxgep,mac_ring_type_t type,uint32_t channel)2942*11878SVenu.Iyer@Sun.COM hxge_ring_get_htable_idx(p_hxge_t hxgep, mac_ring_type_t type, uint32_t channel)
2943*11878SVenu.Iyer@Sun.COM {
2944*11878SVenu.Iyer@Sun.COM int i;
2945*11878SVenu.Iyer@Sun.COM
2946*11878SVenu.Iyer@Sun.COM ASSERT(hxgep->ldgvp != NULL);
2947*11878SVenu.Iyer@Sun.COM
2948*11878SVenu.Iyer@Sun.COM switch (type) {
2949*11878SVenu.Iyer@Sun.COM case MAC_RING_TYPE_RX:
2950*11878SVenu.Iyer@Sun.COM for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2951*11878SVenu.Iyer@Sun.COM if ((hxgep->ldgvp->ldvp[i].is_rxdma) &&
2952*11878SVenu.Iyer@Sun.COM (hxgep->ldgvp->ldvp[i].channel == channel)) {
2953*11878SVenu.Iyer@Sun.COM return ((int)
2954*11878SVenu.Iyer@Sun.COM hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2955*11878SVenu.Iyer@Sun.COM }
2956*11878SVenu.Iyer@Sun.COM }
2957*11878SVenu.Iyer@Sun.COM break;
2958*11878SVenu.Iyer@Sun.COM
2959*11878SVenu.Iyer@Sun.COM case MAC_RING_TYPE_TX:
2960*11878SVenu.Iyer@Sun.COM for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2961*11878SVenu.Iyer@Sun.COM if ((hxgep->ldgvp->ldvp[i].is_txdma) &&
2962*11878SVenu.Iyer@Sun.COM (hxgep->ldgvp->ldvp[i].channel == channel)) {
2963*11878SVenu.Iyer@Sun.COM return ((int)
2964*11878SVenu.Iyer@Sun.COM hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2965*11878SVenu.Iyer@Sun.COM }
2966*11878SVenu.Iyer@Sun.COM }
2967*11878SVenu.Iyer@Sun.COM break;
2968*11878SVenu.Iyer@Sun.COM
2969*11878SVenu.Iyer@Sun.COM default:
2970*11878SVenu.Iyer@Sun.COM break;
2971*11878SVenu.Iyer@Sun.COM }
2972*11878SVenu.Iyer@Sun.COM
2973*11878SVenu.Iyer@Sun.COM return (-1);
2974*11878SVenu.Iyer@Sun.COM }
2975*11878SVenu.Iyer@Sun.COM
29768718SMichael.Speer@Sun.COM /*
29778718SMichael.Speer@Sun.COM * Callback function for the GLDv3 layer to register all rings.
29788718SMichael.Speer@Sun.COM */
29798718SMichael.Speer@Sun.COM /*ARGSUSED*/
29808718SMichael.Speer@Sun.COM static void
hxge_fill_ring(void * arg,mac_ring_type_t type,const int rg_index,const int index,mac_ring_info_t * infop,mac_ring_handle_t rh)29818718SMichael.Speer@Sun.COM hxge_fill_ring(void *arg, mac_ring_type_t type, const int rg_index,
29828718SMichael.Speer@Sun.COM const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
29838718SMichael.Speer@Sun.COM {
29848718SMichael.Speer@Sun.COM p_hxge_t hxgep = arg;
29858718SMichael.Speer@Sun.COM
2986*11878SVenu.Iyer@Sun.COM ASSERT(hxgep != NULL);
2987*11878SVenu.Iyer@Sun.COM ASSERT(infop != NULL);
2988*11878SVenu.Iyer@Sun.COM
29898718SMichael.Speer@Sun.COM switch (type) {
29908718SMichael.Speer@Sun.COM case MAC_RING_TYPE_TX: {
29918718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp;
2992*11878SVenu.Iyer@Sun.COM mac_intr_t *mintr = &infop->mri_intr;
2993*11878SVenu.Iyer@Sun.COM p_hxge_intr_t intrp;
2994*11878SVenu.Iyer@Sun.COM int htable_idx;
29958718SMichael.Speer@Sun.COM
29968718SMichael.Speer@Sun.COM ASSERT((index >= 0) && (index < HXGE_MAX_TDCS));
29978718SMichael.Speer@Sun.COM rhp = &hxgep->tx_ring_handles[index];
29988718SMichael.Speer@Sun.COM rhp->hxgep = hxgep;
29998718SMichael.Speer@Sun.COM rhp->index = index;
30008718SMichael.Speer@Sun.COM rhp->ring_handle = rh;
30018718SMichael.Speer@Sun.COM infop->mri_driver = (mac_ring_driver_t)rhp;
30028718SMichael.Speer@Sun.COM infop->mri_start = hxge_tx_ring_start;
30038718SMichael.Speer@Sun.COM infop->mri_stop = hxge_tx_ring_stop;
30048718SMichael.Speer@Sun.COM infop->mri_tx = hxge_tx_ring_send;
3005*11878SVenu.Iyer@Sun.COM infop->mri_stat = hxge_tx_ring_stat;
3006*11878SVenu.Iyer@Sun.COM
3007*11878SVenu.Iyer@Sun.COM intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3008*11878SVenu.Iyer@Sun.COM htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3009*11878SVenu.Iyer@Sun.COM if (htable_idx >= 0)
3010*11878SVenu.Iyer@Sun.COM mintr->mi_ddi_handle = intrp->htable[htable_idx];
3011*11878SVenu.Iyer@Sun.COM else
3012*11878SVenu.Iyer@Sun.COM mintr->mi_ddi_handle = NULL;
30138718SMichael.Speer@Sun.COM break;
30148718SMichael.Speer@Sun.COM }
3015*11878SVenu.Iyer@Sun.COM
30168718SMichael.Speer@Sun.COM case MAC_RING_TYPE_RX: {
30178718SMichael.Speer@Sun.COM p_hxge_ring_handle_t rhp;
30188718SMichael.Speer@Sun.COM mac_intr_t hxge_mac_intr;
3019*11878SVenu.Iyer@Sun.COM p_hxge_intr_t intrp;
3020*11878SVenu.Iyer@Sun.COM int htable_idx;
30218718SMichael.Speer@Sun.COM
30228718SMichael.Speer@Sun.COM ASSERT((index >= 0) && (index < HXGE_MAX_RDCS));
30238718SMichael.Speer@Sun.COM rhp = &hxgep->rx_ring_handles[index];
30248718SMichael.Speer@Sun.COM rhp->hxgep = hxgep;
30258718SMichael.Speer@Sun.COM rhp->index = index;
30268718SMichael.Speer@Sun.COM rhp->ring_handle = rh;
30278718SMichael.Speer@Sun.COM
30288718SMichael.Speer@Sun.COM /*
30298718SMichael.Speer@Sun.COM * Entrypoint to enable interrupt (disable poll) and
30308718SMichael.Speer@Sun.COM * disable interrupt (enable poll).
30318718SMichael.Speer@Sun.COM */
30328718SMichael.Speer@Sun.COM hxge_mac_intr.mi_handle = (mac_intr_handle_t)rhp;
3033*11878SVenu.Iyer@Sun.COM hxge_mac_intr.mi_enable = (mac_intr_enable_t)hxge_disable_poll;
3034*11878SVenu.Iyer@Sun.COM hxge_mac_intr.mi_disable = (mac_intr_disable_t)hxge_enable_poll;
3035*11878SVenu.Iyer@Sun.COM
3036*11878SVenu.Iyer@Sun.COM intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3037*11878SVenu.Iyer@Sun.COM htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3038*11878SVenu.Iyer@Sun.COM if (htable_idx >= 0)
3039*11878SVenu.Iyer@Sun.COM hxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx];
3040*11878SVenu.Iyer@Sun.COM else
3041*11878SVenu.Iyer@Sun.COM hxge_mac_intr.mi_ddi_handle = NULL;
3042*11878SVenu.Iyer@Sun.COM
30438718SMichael.Speer@Sun.COM infop->mri_driver = (mac_ring_driver_t)rhp;
30448718SMichael.Speer@Sun.COM infop->mri_start = hxge_rx_ring_start;
30458718SMichael.Speer@Sun.COM infop->mri_stop = hxge_rx_ring_stop;
30468718SMichael.Speer@Sun.COM infop->mri_intr = hxge_mac_intr;
30478718SMichael.Speer@Sun.COM infop->mri_poll = hxge_rx_poll;
3048*11878SVenu.Iyer@Sun.COM infop->mri_stat = hxge_rx_ring_stat;
30498718SMichael.Speer@Sun.COM break;
30508718SMichael.Speer@Sun.COM }
3051*11878SVenu.Iyer@Sun.COM
30528718SMichael.Speer@Sun.COM default:
30538718SMichael.Speer@Sun.COM break;
30548718SMichael.Speer@Sun.COM }
30558718SMichael.Speer@Sun.COM }
30568718SMichael.Speer@Sun.COM
30578718SMichael.Speer@Sun.COM /*ARGSUSED*/
30586349Sqs148142 boolean_t
hxge_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)30596349Sqs148142 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
30606349Sqs148142 {
30618718SMichael.Speer@Sun.COM p_hxge_t hxgep = arg;
30626349Sqs148142
30636349Sqs148142 switch (cap) {
30648718SMichael.Speer@Sun.COM case MAC_CAPAB_HCKSUM: {
30658718SMichael.Speer@Sun.COM uint32_t *txflags = cap_data;
30668718SMichael.Speer@Sun.COM
30676349Sqs148142 *txflags = HCKSUM_INET_PARTIAL;
30686349Sqs148142 break;
30698718SMichael.Speer@Sun.COM }
30708718SMichael.Speer@Sun.COM
30718718SMichael.Speer@Sun.COM case MAC_CAPAB_RINGS: {
30728718SMichael.Speer@Sun.COM mac_capab_rings_t *cap_rings = cap_data;
30738718SMichael.Speer@Sun.COM
30748718SMichael.Speer@Sun.COM MUTEX_ENTER(hxgep->genlock);
30758718SMichael.Speer@Sun.COM if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
30768718SMichael.Speer@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
30778718SMichael.Speer@Sun.COM cap_rings->mr_rnum = HXGE_MAX_RDCS;
30788718SMichael.Speer@Sun.COM cap_rings->mr_rget = hxge_fill_ring;
30798718SMichael.Speer@Sun.COM cap_rings->mr_gnum = HXGE_MAX_RX_GROUPS;
30808718SMichael.Speer@Sun.COM cap_rings->mr_gget = hxge_group_get;
30818718SMichael.Speer@Sun.COM cap_rings->mr_gaddring = NULL;
30828718SMichael.Speer@Sun.COM cap_rings->mr_gremring = NULL;
30838718SMichael.Speer@Sun.COM } else {
30848718SMichael.Speer@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
30858718SMichael.Speer@Sun.COM cap_rings->mr_rnum = HXGE_MAX_TDCS;
30868718SMichael.Speer@Sun.COM cap_rings->mr_rget = hxge_fill_ring;
30878718SMichael.Speer@Sun.COM cap_rings->mr_gnum = 0;
30888718SMichael.Speer@Sun.COM cap_rings->mr_gget = NULL;
30898718SMichael.Speer@Sun.COM cap_rings->mr_gaddring = NULL;
30908718SMichael.Speer@Sun.COM cap_rings->mr_gremring = NULL;
30918718SMichael.Speer@Sun.COM }
30928718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
30938718SMichael.Speer@Sun.COM break;
30948718SMichael.Speer@Sun.COM }
30956349Sqs148142
30966349Sqs148142 default:
30976349Sqs148142 return (B_FALSE);
30986349Sqs148142 }
30996349Sqs148142 return (B_TRUE);
31006349Sqs148142 }
31016349Sqs148142
31027584SQiyan.Sun@Sun.COM static boolean_t
hxge_param_locked(mac_prop_id_t pr_num)31037584SQiyan.Sun@Sun.COM hxge_param_locked(mac_prop_id_t pr_num)
31047584SQiyan.Sun@Sun.COM {
31057584SQiyan.Sun@Sun.COM /*
31067584SQiyan.Sun@Sun.COM * All adv_* parameters are locked (read-only) while
31077584SQiyan.Sun@Sun.COM * the device is in any sort of loopback mode ...
31087584SQiyan.Sun@Sun.COM */
31097584SQiyan.Sun@Sun.COM switch (pr_num) {
31107584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP:
31117584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP:
31127584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP:
31137584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP:
31147584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP:
31157584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP:
31167584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP:
31177584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP:
31187584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP:
31197584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP:
31207584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP:
31217584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP:
31227584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG:
31237584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL:
31247584SQiyan.Sun@Sun.COM return (B_TRUE);
31257584SQiyan.Sun@Sun.COM }
31267584SQiyan.Sun@Sun.COM return (B_FALSE);
31277584SQiyan.Sun@Sun.COM }
31287584SQiyan.Sun@Sun.COM
31297584SQiyan.Sun@Sun.COM /*
31307584SQiyan.Sun@Sun.COM * callback functions for set/get of properties
31317584SQiyan.Sun@Sun.COM */
31327584SQiyan.Sun@Sun.COM static int
hxge_m_setprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)31337584SQiyan.Sun@Sun.COM hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
31347584SQiyan.Sun@Sun.COM uint_t pr_valsize, const void *pr_val)
31357584SQiyan.Sun@Sun.COM {
31367584SQiyan.Sun@Sun.COM hxge_t *hxgep = barg;
31377584SQiyan.Sun@Sun.COM p_hxge_stats_t statsp;
31387584SQiyan.Sun@Sun.COM int err = 0;
31397584SQiyan.Sun@Sun.COM uint32_t new_mtu, old_framesize, new_framesize;
31407584SQiyan.Sun@Sun.COM
31417584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop"));
31427584SQiyan.Sun@Sun.COM
31437584SQiyan.Sun@Sun.COM statsp = hxgep->statsp;
31448718SMichael.Speer@Sun.COM MUTEX_ENTER(hxgep->genlock);
31457584SQiyan.Sun@Sun.COM if (statsp->port_stats.lb_mode != hxge_lb_normal &&
31467584SQiyan.Sun@Sun.COM hxge_param_locked(pr_num)) {
31477584SQiyan.Sun@Sun.COM /*
31487584SQiyan.Sun@Sun.COM * All adv_* parameters are locked (read-only)
31497584SQiyan.Sun@Sun.COM * while the device is in any sort of loopback mode.
31507584SQiyan.Sun@Sun.COM */
31517584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31527584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: loopback mode: read only"));
31538718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
31547584SQiyan.Sun@Sun.COM return (EBUSY);
31557584SQiyan.Sun@Sun.COM }
31567584SQiyan.Sun@Sun.COM
31577584SQiyan.Sun@Sun.COM switch (pr_num) {
31587584SQiyan.Sun@Sun.COM /*
31597584SQiyan.Sun@Sun.COM * These properties are either not exist or read only
31607584SQiyan.Sun@Sun.COM */
31617584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP:
31627584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP:
31637584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP:
31647584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP:
31657584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP:
31667584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP:
31677584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP:
31687584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP:
31697584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP:
31707584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP:
31717584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP:
31727584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP:
31737584SQiyan.Sun@Sun.COM case MAC_PROP_STATUS:
31747584SQiyan.Sun@Sun.COM case MAC_PROP_SPEED:
31757584SQiyan.Sun@Sun.COM case MAC_PROP_DUPLEX:
31767584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG:
31777584SQiyan.Sun@Sun.COM /*
31787584SQiyan.Sun@Sun.COM * Flow control is handled in the shared domain and
31797584SQiyan.Sun@Sun.COM * it is readonly here.
31807584SQiyan.Sun@Sun.COM */
31817584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL:
31827584SQiyan.Sun@Sun.COM err = EINVAL;
31837584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31847584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: read only property %d",
31857584SQiyan.Sun@Sun.COM pr_num));
31867584SQiyan.Sun@Sun.COM break;
31877584SQiyan.Sun@Sun.COM
31887584SQiyan.Sun@Sun.COM case MAC_PROP_MTU:
31897584SQiyan.Sun@Sun.COM bcopy(pr_val, &new_mtu, sizeof (new_mtu));
31907584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31917584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: set MTU: %d", new_mtu));
31927584SQiyan.Sun@Sun.COM
31937584SQiyan.Sun@Sun.COM new_framesize = new_mtu + MTU_TO_FRAME_SIZE;
31947584SQiyan.Sun@Sun.COM if (new_framesize == hxgep->vmac.maxframesize) {
31957584SQiyan.Sun@Sun.COM err = 0;
31967584SQiyan.Sun@Sun.COM break;
31977584SQiyan.Sun@Sun.COM }
31987584SQiyan.Sun@Sun.COM
31998118SVasumathi.Sundaram@Sun.COM if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) {
32008118SVasumathi.Sundaram@Sun.COM err = EBUSY;
32018118SVasumathi.Sundaram@Sun.COM break;
32028118SVasumathi.Sundaram@Sun.COM }
32038118SVasumathi.Sundaram@Sun.COM
32047584SQiyan.Sun@Sun.COM if (new_framesize < MIN_FRAME_SIZE ||
32057584SQiyan.Sun@Sun.COM new_framesize > MAX_FRAME_SIZE) {
32067584SQiyan.Sun@Sun.COM err = EINVAL;
32077584SQiyan.Sun@Sun.COM break;
32087584SQiyan.Sun@Sun.COM }
32097584SQiyan.Sun@Sun.COM
32107584SQiyan.Sun@Sun.COM old_framesize = hxgep->vmac.maxframesize;
32117584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize = (uint16_t)new_framesize;
32127584SQiyan.Sun@Sun.COM
32137584SQiyan.Sun@Sun.COM if (hxge_vmac_set_framesize(hxgep)) {
32147584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize =
32157584SQiyan.Sun@Sun.COM (uint16_t)old_framesize;
32167584SQiyan.Sun@Sun.COM err = EINVAL;
32177584SQiyan.Sun@Sun.COM break;
32187584SQiyan.Sun@Sun.COM }
32197584SQiyan.Sun@Sun.COM
32207584SQiyan.Sun@Sun.COM err = mac_maxsdu_update(hxgep->mach, new_mtu);
32217584SQiyan.Sun@Sun.COM if (err) {
32227584SQiyan.Sun@Sun.COM hxgep->vmac.maxframesize =
32237584SQiyan.Sun@Sun.COM (uint16_t)old_framesize;
32247584SQiyan.Sun@Sun.COM (void) hxge_vmac_set_framesize(hxgep);
32257584SQiyan.Sun@Sun.COM }
32267584SQiyan.Sun@Sun.COM
32277584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32287584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: set MTU: %d maxframe %d",
32297584SQiyan.Sun@Sun.COM new_mtu, hxgep->vmac.maxframesize));
32307584SQiyan.Sun@Sun.COM break;
32317584SQiyan.Sun@Sun.COM
32327584SQiyan.Sun@Sun.COM case MAC_PROP_PRIVATE:
32337584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32347584SQiyan.Sun@Sun.COM "==> hxge_m_setprop: private property"));
32357584SQiyan.Sun@Sun.COM err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize,
32367584SQiyan.Sun@Sun.COM pr_val);
32377584SQiyan.Sun@Sun.COM break;
32387584SQiyan.Sun@Sun.COM
32397584SQiyan.Sun@Sun.COM default:
32407584SQiyan.Sun@Sun.COM err = ENOTSUP;
32417584SQiyan.Sun@Sun.COM break;
32427584SQiyan.Sun@Sun.COM }
32437584SQiyan.Sun@Sun.COM
32448718SMichael.Speer@Sun.COM MUTEX_EXIT(hxgep->genlock);
32457584SQiyan.Sun@Sun.COM
32467584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32477584SQiyan.Sun@Sun.COM "<== hxge_m_setprop (return %d)", err));
32487584SQiyan.Sun@Sun.COM
32497584SQiyan.Sun@Sun.COM return (err);
32507584SQiyan.Sun@Sun.COM }
32517584SQiyan.Sun@Sun.COM
32527584SQiyan.Sun@Sun.COM static int
hxge_m_getprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)32537584SQiyan.Sun@Sun.COM hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
3254*11878SVenu.Iyer@Sun.COM uint_t pr_valsize, void *pr_val)
32557584SQiyan.Sun@Sun.COM {
32567584SQiyan.Sun@Sun.COM hxge_t *hxgep = barg;
32577584SQiyan.Sun@Sun.COM p_hxge_stats_t statsp = hxgep->statsp;
32587584SQiyan.Sun@Sun.COM int err = 0;
32597584SQiyan.Sun@Sun.COM link_flowctrl_t fl;
32607584SQiyan.Sun@Sun.COM uint64_t tmp = 0;
32617584SQiyan.Sun@Sun.COM link_state_t ls;
32627584SQiyan.Sun@Sun.COM
32637584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32647584SQiyan.Sun@Sun.COM "==> hxge_m_getprop: pr_num %d", pr_num));
32657584SQiyan.Sun@Sun.COM
32667584SQiyan.Sun@Sun.COM switch (pr_num) {
32677584SQiyan.Sun@Sun.COM case MAC_PROP_DUPLEX:
32687584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
32697584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32707584SQiyan.Sun@Sun.COM "==> hxge_m_getprop: duplex mode %d",
32717584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val));
32727584SQiyan.Sun@Sun.COM break;
32737584SQiyan.Sun@Sun.COM
32747584SQiyan.Sun@Sun.COM case MAC_PROP_SPEED:
3275*11878SVenu.Iyer@Sun.COM ASSERT(pr_valsize >= sizeof (uint64_t));
32767584SQiyan.Sun@Sun.COM tmp = statsp->mac_stats.link_speed * 1000000ull;
32777584SQiyan.Sun@Sun.COM bcopy(&tmp, pr_val, sizeof (tmp));
32787584SQiyan.Sun@Sun.COM break;
32797584SQiyan.Sun@Sun.COM
32807584SQiyan.Sun@Sun.COM case MAC_PROP_STATUS:
3281*11878SVenu.Iyer@Sun.COM ASSERT(pr_valsize >= sizeof (link_state_t));
32827584SQiyan.Sun@Sun.COM if (!statsp->mac_stats.link_up)
32837584SQiyan.Sun@Sun.COM ls = LINK_STATE_DOWN;
32847584SQiyan.Sun@Sun.COM else
32857584SQiyan.Sun@Sun.COM ls = LINK_STATE_UP;
32867584SQiyan.Sun@Sun.COM bcopy(&ls, pr_val, sizeof (ls));
32877584SQiyan.Sun@Sun.COM break;
32887584SQiyan.Sun@Sun.COM
32897584SQiyan.Sun@Sun.COM case MAC_PROP_FLOWCTRL:
32907584SQiyan.Sun@Sun.COM /*
32917584SQiyan.Sun@Sun.COM * Flow control is supported by the shared domain and
32927584SQiyan.Sun@Sun.COM * it is currently transmit only
32937584SQiyan.Sun@Sun.COM */
3294*11878SVenu.Iyer@Sun.COM ASSERT(pr_valsize < sizeof (link_flowctrl_t));
32957584SQiyan.Sun@Sun.COM fl = LINK_FLOWCTRL_TX;
32967584SQiyan.Sun@Sun.COM bcopy(&fl, pr_val, sizeof (fl));
32977584SQiyan.Sun@Sun.COM break;
32987584SQiyan.Sun@Sun.COM case MAC_PROP_AUTONEG:
32997584SQiyan.Sun@Sun.COM /* 10G link only and it is not negotiable */
33007584SQiyan.Sun@Sun.COM *(uint8_t *)pr_val = 0;
33017584SQiyan.Sun@Sun.COM break;
33027584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000FDX_CAP:
33037584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100FDX_CAP:
33047584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10FDX_CAP:
33057584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_1000HDX_CAP:
33067584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_100HDX_CAP:
33077584SQiyan.Sun@Sun.COM case MAC_PROP_ADV_10HDX_CAP:
33087584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000FDX_CAP:
33097584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100FDX_CAP:
33107584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10FDX_CAP:
33117584SQiyan.Sun@Sun.COM case MAC_PROP_EN_1000HDX_CAP:
33127584SQiyan.Sun@Sun.COM case MAC_PROP_EN_100HDX_CAP:
33137584SQiyan.Sun@Sun.COM case MAC_PROP_EN_10HDX_CAP:
33147584SQiyan.Sun@Sun.COM err = ENOTSUP;
33157584SQiyan.Sun@Sun.COM break;
33167584SQiyan.Sun@Sun.COM
33177584SQiyan.Sun@Sun.COM case MAC_PROP_PRIVATE:
3318*11878SVenu.Iyer@Sun.COM err = hxge_get_priv_prop(hxgep, pr_name, pr_valsize,
3319*11878SVenu.Iyer@Sun.COM pr_val);
33207584SQiyan.Sun@Sun.COM break;
3321*11878SVenu.Iyer@Sun.COM
33227584SQiyan.Sun@Sun.COM default:
33237584SQiyan.Sun@Sun.COM err = EINVAL;
33247584SQiyan.Sun@Sun.COM break;
33257584SQiyan.Sun@Sun.COM }
33267584SQiyan.Sun@Sun.COM
33277584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop"));
33287584SQiyan.Sun@Sun.COM
33297584SQiyan.Sun@Sun.COM return (err);
33307584SQiyan.Sun@Sun.COM }
33317584SQiyan.Sun@Sun.COM
3332*11878SVenu.Iyer@Sun.COM static void
hxge_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)3333*11878SVenu.Iyer@Sun.COM hxge_m_propinfo(void *arg, const char *pr_name,
3334*11878SVenu.Iyer@Sun.COM mac_prop_id_t pr_num, mac_prop_info_handle_t prh)
3335*11878SVenu.Iyer@Sun.COM {
3336*11878SVenu.Iyer@Sun.COM _NOTE(ARGUNUSED(arg));
3337*11878SVenu.Iyer@Sun.COM switch (pr_num) {
3338*11878SVenu.Iyer@Sun.COM case MAC_PROP_DUPLEX:
3339*11878SVenu.Iyer@Sun.COM case MAC_PROP_SPEED:
3340*11878SVenu.Iyer@Sun.COM case MAC_PROP_STATUS:
3341*11878SVenu.Iyer@Sun.COM case MAC_PROP_AUTONEG:
3342*11878SVenu.Iyer@Sun.COM case MAC_PROP_FLOWCTRL:
3343*11878SVenu.Iyer@Sun.COM mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
3344*11878SVenu.Iyer@Sun.COM break;
3345*11878SVenu.Iyer@Sun.COM
3346*11878SVenu.Iyer@Sun.COM case MAC_PROP_MTU:
3347*11878SVenu.Iyer@Sun.COM mac_prop_info_set_range_uint32(prh,
3348*11878SVenu.Iyer@Sun.COM MIN_FRAME_SIZE - MTU_TO_FRAME_SIZE,
3349*11878SVenu.Iyer@Sun.COM MAX_FRAME_SIZE - MTU_TO_FRAME_SIZE);
3350*11878SVenu.Iyer@Sun.COM break;
3351*11878SVenu.Iyer@Sun.COM
3352*11878SVenu.Iyer@Sun.COM case MAC_PROP_PRIVATE: {
3353*11878SVenu.Iyer@Sun.COM char valstr[MAXNAMELEN];
3354*11878SVenu.Iyer@Sun.COM
3355*11878SVenu.Iyer@Sun.COM bzero(valstr, sizeof (valstr));
3356*11878SVenu.Iyer@Sun.COM
3357*11878SVenu.Iyer@Sun.COM /* Receive Interrupt Blanking Parameters */
3358*11878SVenu.Iyer@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3359*11878SVenu.Iyer@Sun.COM (void) snprintf(valstr, sizeof (valstr), "%d",
3360*11878SVenu.Iyer@Sun.COM RXDMA_RCR_TO_DEFAULT);
3361*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3362*11878SVenu.Iyer@Sun.COM (void) snprintf(valstr, sizeof (valstr), "%d",
3363*11878SVenu.Iyer@Sun.COM RXDMA_RCR_PTHRES_DEFAULT);
3364*11878SVenu.Iyer@Sun.COM
3365*11878SVenu.Iyer@Sun.COM /* Classification and Load Distribution Configuration */
3366*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
3367*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
3368*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
3369*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
3370*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
3371*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
3372*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
3373*11878SVenu.Iyer@Sun.COM strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3374*11878SVenu.Iyer@Sun.COM (void) snprintf(valstr, sizeof (valstr), "%d",
3375*11878SVenu.Iyer@Sun.COM HXGE_CLASS_TCAM_LOOKUP);
3376*11878SVenu.Iyer@Sun.COM }
3377*11878SVenu.Iyer@Sun.COM
3378*11878SVenu.Iyer@Sun.COM if (strlen(valstr) > 0)
3379*11878SVenu.Iyer@Sun.COM mac_prop_info_set_default_str(prh, valstr);
3380*11878SVenu.Iyer@Sun.COM break;
3381*11878SVenu.Iyer@Sun.COM }
3382*11878SVenu.Iyer@Sun.COM }
3383*11878SVenu.Iyer@Sun.COM }
3384*11878SVenu.Iyer@Sun.COM
3385*11878SVenu.Iyer@Sun.COM
33867584SQiyan.Sun@Sun.COM /* ARGSUSED */
33877584SQiyan.Sun@Sun.COM static int
hxge_set_priv_prop(p_hxge_t hxgep,const char * pr_name,uint_t pr_valsize,const void * pr_val)33887584SQiyan.Sun@Sun.COM hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
33897584SQiyan.Sun@Sun.COM const void *pr_val)
33907584SQiyan.Sun@Sun.COM {
33917584SQiyan.Sun@Sun.COM p_hxge_param_t param_arr = hxgep->param_arr;
33927584SQiyan.Sun@Sun.COM int err = 0;
33937584SQiyan.Sun@Sun.COM
33947584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
33957584SQiyan.Sun@Sun.COM "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val));
33967584SQiyan.Sun@Sun.COM
33977584SQiyan.Sun@Sun.COM if (pr_val == NULL) {
33987584SQiyan.Sun@Sun.COM return (EINVAL);
33997584SQiyan.Sun@Sun.COM }
34007584SQiyan.Sun@Sun.COM
34017584SQiyan.Sun@Sun.COM /* Blanking */
34027584SQiyan.Sun@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
34037584SQiyan.Sun@Sun.COM err = hxge_param_rx_intr_time(hxgep, NULL, NULL,
34047584SQiyan.Sun@Sun.COM (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_time]);
34057584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
34067584SQiyan.Sun@Sun.COM err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL,
34077584SQiyan.Sun@Sun.COM (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_pkts]);
34087584SQiyan.Sun@Sun.COM
34097584SQiyan.Sun@Sun.COM /* Classification */
34107584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
34117584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34127584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]);
34137584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
34147584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34157584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_udp]);
34167584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
34177584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34187584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_ah]);
34197584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
34207584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34217584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]);
34227584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
34237584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34247584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]);
34257584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
34267584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34277584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_udp]);
34287584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
34297584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34307584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_ah]);
34317584SQiyan.Sun@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
34327584SQiyan.Sun@Sun.COM err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34337584SQiyan.Sun@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]);
34347584SQiyan.Sun@Sun.COM } else {
34357584SQiyan.Sun@Sun.COM err = EINVAL;
34367584SQiyan.Sun@Sun.COM }
34377584SQiyan.Sun@Sun.COM
34387584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
34397584SQiyan.Sun@Sun.COM "<== hxge_set_priv_prop: err %d", err));
34407584SQiyan.Sun@Sun.COM
34417584SQiyan.Sun@Sun.COM return (err);
34427584SQiyan.Sun@Sun.COM }
34437584SQiyan.Sun@Sun.COM
34447584SQiyan.Sun@Sun.COM static int
hxge_get_priv_prop(p_hxge_t hxgep,const char * pr_name,uint_t pr_valsize,void * pr_val)3445*11878SVenu.Iyer@Sun.COM hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
3446*11878SVenu.Iyer@Sun.COM void *pr_val)
34477584SQiyan.Sun@Sun.COM {
34487584SQiyan.Sun@Sun.COM p_hxge_param_t param_arr = hxgep->param_arr;
34497584SQiyan.Sun@Sun.COM char valstr[MAXNAMELEN];
34507584SQiyan.Sun@Sun.COM int err = 0;
34517584SQiyan.Sun@Sun.COM uint_t strsize;
34527584SQiyan.Sun@Sun.COM int value = 0;
34537584SQiyan.Sun@Sun.COM
34547584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
34557584SQiyan.Sun@Sun.COM "==> hxge_get_priv_prop: property %s", pr_name));
34567584SQiyan.Sun@Sun.COM
3457*11878SVenu.Iyer@Sun.COM /* Receive Interrupt Blanking Parameters */
3458*11878SVenu.Iyer@Sun.COM if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3459*11878SVenu.Iyer@Sun.COM value = hxgep->intr_timeout;
3460*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3461*11878SVenu.Iyer@Sun.COM value = hxgep->intr_threshold;
3462*11878SVenu.Iyer@Sun.COM
3463*11878SVenu.Iyer@Sun.COM /* Classification and Load Distribution Configuration */
3464*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3465*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3466*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]);
3467*11878SVenu.Iyer@Sun.COM
3468*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv4_tcp].value;
3469*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3470*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3471*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_udp]);
3472*11878SVenu.Iyer@Sun.COM
3473*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv4_udp].value;
3474*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3475*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3476*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_ah]);
3477*11878SVenu.Iyer@Sun.COM
3478*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv4_ah].value;
3479*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3480*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3481*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]);
3482*11878SVenu.Iyer@Sun.COM
3483*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv4_sctp].value;
3484*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3485*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3486*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]);
3487*11878SVenu.Iyer@Sun.COM
3488*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv6_tcp].value;
3489*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3490*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3491*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_udp]);
3492*11878SVenu.Iyer@Sun.COM
3493*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv6_udp].value;
3494*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3495*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3496*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_ah]);
3497*11878SVenu.Iyer@Sun.COM
3498*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv6_ah].value;
3499*11878SVenu.Iyer@Sun.COM } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3500*11878SVenu.Iyer@Sun.COM err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3501*11878SVenu.Iyer@Sun.COM (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]);
3502*11878SVenu.Iyer@Sun.COM
3503*11878SVenu.Iyer@Sun.COM value = (int)param_arr[param_class_opt_ipv6_sctp].value;
35047584SQiyan.Sun@Sun.COM } else {
3505*11878SVenu.Iyer@Sun.COM err = EINVAL;
35067584SQiyan.Sun@Sun.COM }
35077584SQiyan.Sun@Sun.COM
35087584SQiyan.Sun@Sun.COM if (err == 0) {
35097584SQiyan.Sun@Sun.COM (void) snprintf(valstr, sizeof (valstr), "0x%x", value);
35107584SQiyan.Sun@Sun.COM
35117584SQiyan.Sun@Sun.COM strsize = (uint_t)strlen(valstr);
35127584SQiyan.Sun@Sun.COM if (pr_valsize < strsize) {
35137584SQiyan.Sun@Sun.COM err = ENOBUFS;
35147584SQiyan.Sun@Sun.COM } else {
35157584SQiyan.Sun@Sun.COM (void) strlcpy(pr_val, valstr, pr_valsize);
35167584SQiyan.Sun@Sun.COM }
35177584SQiyan.Sun@Sun.COM }
35187584SQiyan.Sun@Sun.COM
35197584SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
35207584SQiyan.Sun@Sun.COM "<== hxge_get_priv_prop: return %d", err));
35217584SQiyan.Sun@Sun.COM
35227584SQiyan.Sun@Sun.COM return (err);
35237584SQiyan.Sun@Sun.COM }
35246349Sqs148142 /*
35256349Sqs148142 * Module loading and removing entry points.
35266349Sqs148142 */
35276349Sqs148142 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach,
35287918SQiyan.Sun@Sun.COM nodev, NULL, D_MP, NULL, NULL);
35296349Sqs148142
35306349Sqs148142 extern struct mod_ops mod_driverops;
35316349Sqs148142
35326349Sqs148142 #define HXGE_DESC_VER "HXGE 10Gb Ethernet Driver"
35336349Sqs148142
35346349Sqs148142 /*
35356349Sqs148142 * Module linkage information for the kernel.
35366349Sqs148142 */
35376349Sqs148142 static struct modldrv hxge_modldrv = {
35386349Sqs148142 &mod_driverops,
35396349Sqs148142 HXGE_DESC_VER,
35406349Sqs148142 &hxge_dev_ops
35416349Sqs148142 };
35426349Sqs148142
35436349Sqs148142 static struct modlinkage modlinkage = {
35446349Sqs148142 MODREV_1, (void *) &hxge_modldrv, NULL
35456349Sqs148142 };
35466349Sqs148142
35476349Sqs148142 int
_init(void)35486349Sqs148142 _init(void)
35496349Sqs148142 {
35506349Sqs148142 int status;
35516349Sqs148142
35526349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
35536349Sqs148142 mac_init_ops(&hxge_dev_ops, "hxge");
35546349Sqs148142 status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0);
35556349Sqs148142 if (status != 0) {
35566349Sqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL,
35576349Sqs148142 "failed to init device soft state"));
35586349Sqs148142 mac_fini_ops(&hxge_dev_ops);
35596349Sqs148142 goto _init_exit;
35606349Sqs148142 }
35616349Sqs148142
35626349Sqs148142 status = mod_install(&modlinkage);
35636349Sqs148142 if (status != 0) {
35646349Sqs148142 ddi_soft_state_fini(&hxge_list);
35656349Sqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed"));
35666349Sqs148142 goto _init_exit;
35676349Sqs148142 }
35686349Sqs148142
35696349Sqs148142 MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL);
35706349Sqs148142
35716349Sqs148142 _init_exit:
35726349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
35736349Sqs148142
35746349Sqs148142 return (status);
35756349Sqs148142 }
35766349Sqs148142
35776349Sqs148142 int
_fini(void)35786349Sqs148142 _fini(void)
35796349Sqs148142 {
35806349Sqs148142 int status;
35816349Sqs148142
35826349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
35836349Sqs148142
35846349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
35856349Sqs148142
35866349Sqs148142 if (hxge_mblks_pending)
35876349Sqs148142 return (EBUSY);
35886349Sqs148142
35896349Sqs148142 status = mod_remove(&modlinkage);
35906349Sqs148142 if (status != DDI_SUCCESS) {
35916349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL,
35926349Sqs148142 "Module removal failed 0x%08x", status));
35936349Sqs148142 goto _fini_exit;
35946349Sqs148142 }
35956349Sqs148142
35966349Sqs148142 mac_fini_ops(&hxge_dev_ops);
35976349Sqs148142
35986349Sqs148142 ddi_soft_state_fini(&hxge_list);
35996349Sqs148142
36006349Sqs148142 MUTEX_DESTROY(&hxge_common_lock);
36016349Sqs148142
36026349Sqs148142 _fini_exit:
36036349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
36046349Sqs148142
36056349Sqs148142 return (status);
36066349Sqs148142 }
36076349Sqs148142
36086349Sqs148142 int
_info(struct modinfo * modinfop)36096349Sqs148142 _info(struct modinfo *modinfop)
36106349Sqs148142 {
36116349Sqs148142 int status;
36126349Sqs148142
36136349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
36146349Sqs148142 status = mod_info(&modlinkage, modinfop);
36156349Sqs148142 HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
36166349Sqs148142
36176349Sqs148142 return (status);
36186349Sqs148142 }
36196349Sqs148142
36206349Sqs148142 /*ARGSUSED*/
362111257SMichael.Speer@Sun.COM static hxge_status_t
hxge_add_intrs(p_hxge_t hxgep)36226349Sqs148142 hxge_add_intrs(p_hxge_t hxgep)
36236349Sqs148142 {
36246349Sqs148142 int intr_types;
36256349Sqs148142 int type = 0;
36266349Sqs148142 int ddi_status = DDI_SUCCESS;
36276349Sqs148142 hxge_status_t status = HXGE_OK;
36286349Sqs148142
36296349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs"));
36306349Sqs148142
36316349Sqs148142 hxgep->hxge_intr_type.intr_registered = B_FALSE;
36326349Sqs148142 hxgep->hxge_intr_type.intr_enabled = B_FALSE;
36336349Sqs148142 hxgep->hxge_intr_type.msi_intx_cnt = 0;
36346349Sqs148142 hxgep->hxge_intr_type.intr_added = 0;
36356349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable = B_FALSE;
36366349Sqs148142 hxgep->hxge_intr_type.intr_type = 0;
36376349Sqs148142
36386349Sqs148142 if (hxge_msi_enable) {
36396349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable = B_TRUE;
36406349Sqs148142 }
36416349Sqs148142
36426349Sqs148142 /* Get the supported interrupt types */
36436349Sqs148142 if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types))
36446349Sqs148142 != DDI_SUCCESS) {
36456349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: "
36466349Sqs148142 "ddi_intr_get_supported_types failed: status 0x%08x",
36476349Sqs148142 ddi_status));
36486349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
36496349Sqs148142 }
36506349Sqs148142
36516349Sqs148142 hxgep->hxge_intr_type.intr_types = intr_types;
36526349Sqs148142
36536349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36546349Sqs148142 "ddi_intr_get_supported_types: 0x%08x", intr_types));
36556349Sqs148142
36566349Sqs148142 /*
36576349Sqs148142 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable:
36586349Sqs148142 * (1): 1 - MSI
36596349Sqs148142 * (2): 2 - MSI-X
36606349Sqs148142 * others - FIXED
36616349Sqs148142 */
36626349Sqs148142 switch (hxge_msi_enable) {
36636349Sqs148142 default:
36646349Sqs148142 type = DDI_INTR_TYPE_FIXED;
36656349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36666349Sqs148142 "use fixed (intx emulation) type %08x", type));
36676349Sqs148142 break;
36686349Sqs148142
36696349Sqs148142 case 2:
36706349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36716349Sqs148142 "ddi_intr_get_supported_types: 0x%08x", intr_types));
36726349Sqs148142 if (intr_types & DDI_INTR_TYPE_MSIX) {
36736349Sqs148142 type = DDI_INTR_TYPE_MSIX;
36746349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
36756349Sqs148142 "==> hxge_add_intrs: "
36766349Sqs148142 "ddi_intr_get_supported_types: MSIX 0x%08x", type));
36776349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_MSI) {
36786349Sqs148142 type = DDI_INTR_TYPE_MSI;
36796349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
36806349Sqs148142 "==> hxge_add_intrs: "
36816349Sqs148142 "ddi_intr_get_supported_types: MSI 0x%08x", type));
36826349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
36836349Sqs148142 type = DDI_INTR_TYPE_FIXED;
36846349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36856349Sqs148142 "ddi_intr_get_supported_types: MSXED0x%08x", type));
36866349Sqs148142 }
36876349Sqs148142 break;
36886349Sqs148142
36896349Sqs148142 case 1:
36906349Sqs148142 if (intr_types & DDI_INTR_TYPE_MSI) {
36916349Sqs148142 type = DDI_INTR_TYPE_MSI;
36926349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
36936349Sqs148142 "==> hxge_add_intrs: "
36946349Sqs148142 "ddi_intr_get_supported_types: MSI 0x%08x", type));
36956349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_MSIX) {
36966349Sqs148142 type = DDI_INTR_TYPE_MSIX;
36976349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
36986349Sqs148142 "==> hxge_add_intrs: "
36996349Sqs148142 "ddi_intr_get_supported_types: MSIX 0x%08x", type));
37006349Sqs148142 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
37016349Sqs148142 type = DDI_INTR_TYPE_FIXED;
37026349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
37036349Sqs148142 "==> hxge_add_intrs: "
37046349Sqs148142 "ddi_intr_get_supported_types: MSXED0x%08x", type));
37056349Sqs148142 }
37066349Sqs148142 }
37076349Sqs148142
37086349Sqs148142 hxgep->hxge_intr_type.intr_type = type;
37096349Sqs148142 if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
37106349Sqs148142 type == DDI_INTR_TYPE_FIXED) &&
37116349Sqs148142 hxgep->hxge_intr_type.niu_msi_enable) {
37126349Sqs148142 if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) {
37136349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37146349Sqs148142 " hxge_add_intrs: "
37156349Sqs148142 " hxge_add_intrs_adv failed: status 0x%08x",
37166349Sqs148142 status));
37176349Sqs148142 return (status);
37186349Sqs148142 } else {
37196349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: "
37206349Sqs148142 "interrupts registered : type %d", type));
37216349Sqs148142 hxgep->hxge_intr_type.intr_registered = B_TRUE;
37226349Sqs148142
37236349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
37246349Sqs148142 "\nAdded advanced hxge add_intr_adv "
37256349Sqs148142 "intr type 0x%x\n", type));
37266349Sqs148142
37276349Sqs148142 return (status);
37286349Sqs148142 }
37296349Sqs148142 }
37306349Sqs148142
37316349Sqs148142 if (!hxgep->hxge_intr_type.intr_registered) {
37326349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37336349Sqs148142 "==> hxge_add_intrs: failed to register interrupts"));
37346349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
37356349Sqs148142 }
37366349Sqs148142
37376349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs"));
37386349Sqs148142
37396349Sqs148142 return (status);
37406349Sqs148142 }
37416349Sqs148142
37426349Sqs148142 /*ARGSUSED*/
37436349Sqs148142 static hxge_status_t
hxge_add_intrs_adv(p_hxge_t hxgep)37446349Sqs148142 hxge_add_intrs_adv(p_hxge_t hxgep)
37456349Sqs148142 {
37466349Sqs148142 int intr_type;
37476349Sqs148142 p_hxge_intr_t intrp;
37486349Sqs148142 hxge_status_t status;
37496349Sqs148142
37506349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv"));
37516349Sqs148142
37526349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
37536349Sqs148142 intr_type = intrp->intr_type;
37546349Sqs148142
37556349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x",
37566349Sqs148142 intr_type));
37576349Sqs148142
37586349Sqs148142 switch (intr_type) {
37596349Sqs148142 case DDI_INTR_TYPE_MSI: /* 0x2 */
37606349Sqs148142 case DDI_INTR_TYPE_MSIX: /* 0x4 */
37616349Sqs148142 status = hxge_add_intrs_adv_type(hxgep, intr_type);
37626349Sqs148142 break;
37636349Sqs148142
37646349Sqs148142 case DDI_INTR_TYPE_FIXED: /* 0x1 */
37656349Sqs148142 status = hxge_add_intrs_adv_type_fix(hxgep, intr_type);
37666349Sqs148142 break;
37676349Sqs148142
37686349Sqs148142 default:
37696349Sqs148142 status = HXGE_ERROR;
37706349Sqs148142 break;
37716349Sqs148142 }
37726349Sqs148142
37736349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv"));
37746349Sqs148142
37756349Sqs148142 return (status);
37766349Sqs148142 }
37776349Sqs148142
37786349Sqs148142 /*ARGSUSED*/
37796349Sqs148142 static hxge_status_t
hxge_add_intrs_adv_type(p_hxge_t hxgep,uint32_t int_type)37806349Sqs148142 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type)
37816349Sqs148142 {
37826349Sqs148142 dev_info_t *dip = hxgep->dip;
37836349Sqs148142 p_hxge_ldg_t ldgp;
37846349Sqs148142 p_hxge_intr_t intrp;
37856349Sqs148142 uint_t *inthandler;
37866349Sqs148142 void *arg1, *arg2;
37876349Sqs148142 int behavior;
37886349Sqs148142 int nintrs, navail;
37898366SQiyan.Sun@Sun.COM int nactual, nrequired, nrequest;
37906349Sqs148142 int inum = 0;
37916349Sqs148142 int loop = 0;
37926349Sqs148142 int x, y;
37936349Sqs148142 int ddi_status = DDI_SUCCESS;
37946349Sqs148142 hxge_status_t status = HXGE_OK;
37956349Sqs148142
37966349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type"));
37976349Sqs148142
37986349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
37996349Sqs148142
38006349Sqs148142 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
38016349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
38026349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38036349Sqs148142 "ddi_intr_get_nintrs() failed, status: 0x%x%, "
38046349Sqs148142 "nintrs: %d", ddi_status, nintrs));
38056349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
38066349Sqs148142 }
38076349Sqs148142
38086349Sqs148142 ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
38096349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
38106349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38116349Sqs148142 "ddi_intr_get_navail() failed, status: 0x%x%, "
38126349Sqs148142 "nintrs: %d", ddi_status, navail));
38136349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
38146349Sqs148142 }
38156349Sqs148142
38166349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
38176349Sqs148142 "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d",
38186349Sqs148142 int_type, nintrs, navail));
38196349Sqs148142
38208366SQiyan.Sun@Sun.COM /* PSARC/2007/453 MSI-X interrupt limit override */
38218366SQiyan.Sun@Sun.COM if (int_type == DDI_INTR_TYPE_MSIX) {
38228366SQiyan.Sun@Sun.COM nrequest = hxge_create_msi_property(hxgep);
38238366SQiyan.Sun@Sun.COM if (nrequest < navail) {
38248366SQiyan.Sun@Sun.COM navail = nrequest;
38258366SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, INT_CTL,
38268366SQiyan.Sun@Sun.COM "hxge_add_intrs_adv_type: nintrs %d "
38278366SQiyan.Sun@Sun.COM "navail %d (nrequest %d)",
38288366SQiyan.Sun@Sun.COM nintrs, navail, nrequest));
38298366SQiyan.Sun@Sun.COM }
38308366SQiyan.Sun@Sun.COM }
38318366SQiyan.Sun@Sun.COM
38326349Sqs148142 if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
38336349Sqs148142 /* MSI must be power of 2 */
38346349Sqs148142 if ((navail & 16) == 16) {
38356349Sqs148142 navail = 16;
38366349Sqs148142 } else if ((navail & 8) == 8) {
38376349Sqs148142 navail = 8;
38386349Sqs148142 } else if ((navail & 4) == 4) {
38396349Sqs148142 navail = 4;
38406349Sqs148142 } else if ((navail & 2) == 2) {
38416349Sqs148142 navail = 2;
38426349Sqs148142 } else {
38436349Sqs148142 navail = 1;
38446349Sqs148142 }
38456349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
38466349Sqs148142 "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
38476349Sqs148142 "navail %d", nintrs, navail));
38486349Sqs148142 }
38496349Sqs148142
38506349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
38516349Sqs148142 "requesting: intr type %d nintrs %d, navail %d",
38526349Sqs148142 int_type, nintrs, navail));
38536349Sqs148142
38546349Sqs148142 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
38556349Sqs148142 DDI_INTR_ALLOC_NORMAL);
38566349Sqs148142 intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
38576349Sqs148142 intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP);
38586349Sqs148142
38596349Sqs148142 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
38606349Sqs148142 navail, &nactual, behavior);
38616349Sqs148142 if (ddi_status != DDI_SUCCESS || nactual == 0) {
38626349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38636349Sqs148142 " ddi_intr_alloc() failed: %d", ddi_status));
38646349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
38656349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
38666349Sqs148142 }
38676349Sqs148142
38686349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
38696349Sqs148142 "ddi_intr_alloc() returned: navail %d nactual %d",
38706349Sqs148142 navail, nactual));
38716349Sqs148142
38726349Sqs148142 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
38736349Sqs148142 (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
38746349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38756349Sqs148142 " ddi_intr_get_pri() failed: %d", ddi_status));
38766349Sqs148142 /* Free already allocated interrupts */
38776349Sqs148142 for (y = 0; y < nactual; y++) {
38786349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
38796349Sqs148142 }
38806349Sqs148142
38816349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
38826349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
38836349Sqs148142 }
38846349Sqs148142
38856349Sqs148142 nrequired = 0;
38866349Sqs148142 status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
38876349Sqs148142 if (status != HXGE_OK) {
38886349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38896349Sqs148142 "hxge_add_intrs_adv_typ:hxge_ldgv_init "
38906349Sqs148142 "failed: 0x%x", status));
38916349Sqs148142 /* Free already allocated interrupts */
38926349Sqs148142 for (y = 0; y < nactual; y++) {
38936349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
38946349Sqs148142 }
38956349Sqs148142
38966349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
38976349Sqs148142 return (status);
38986349Sqs148142 }
38996349Sqs148142
39006349Sqs148142 ldgp = hxgep->ldgvp->ldgp;
39016349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39026349Sqs148142 "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual));
39036349Sqs148142
39046349Sqs148142 if (nactual < nrequired)
39056349Sqs148142 loop = nactual;
39066349Sqs148142 else
39076349Sqs148142 loop = nrequired;
39086349Sqs148142
39096349Sqs148142 for (x = 0; x < loop; x++, ldgp++) {
39106349Sqs148142 ldgp->vector = (uint8_t)x;
39116349Sqs148142 arg1 = ldgp->ldvp;
39126349Sqs148142 arg2 = hxgep;
39136349Sqs148142 if (ldgp->nldvs == 1) {
39146349Sqs148142 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
39156349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39166349Sqs148142 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
39176349Sqs148142 "1-1 int handler (entry %d)\n",
39186349Sqs148142 arg1, arg2, x));
39196349Sqs148142 } else if (ldgp->nldvs > 1) {
39206349Sqs148142 inthandler = (uint_t *)ldgp->sys_intr_handler;
39216349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39226349Sqs148142 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
39236349Sqs148142 "nldevs %d int handler (entry %d)\n",
39246349Sqs148142 arg1, arg2, ldgp->nldvs, x));
39256349Sqs148142 }
39266349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39276349Sqs148142 "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
39286349Sqs148142 "htable 0x%llx", x, intrp->htable[x]));
39296349Sqs148142
39306349Sqs148142 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
39316349Sqs148142 (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
39326349Sqs148142 DDI_SUCCESS) {
39336349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
39346349Sqs148142 "==> hxge_add_intrs_adv_type: failed #%d "
39356349Sqs148142 "status 0x%x", x, ddi_status));
39366349Sqs148142 for (y = 0; y < intrp->intr_added; y++) {
39376349Sqs148142 (void) ddi_intr_remove_handler(
39386349Sqs148142 intrp->htable[y]);
39396349Sqs148142 }
39406349Sqs148142
39416349Sqs148142 /* Free already allocated intr */
39426349Sqs148142 for (y = 0; y < nactual; y++) {
39436349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
39446349Sqs148142 }
39456349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
39466349Sqs148142
39476349Sqs148142 (void) hxge_ldgv_uninit(hxgep);
39486349Sqs148142
39496349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
39506349Sqs148142 }
39516349Sqs148142
3952*11878SVenu.Iyer@Sun.COM ldgp->htable_idx = x;
39536349Sqs148142 intrp->intr_added++;
39546349Sqs148142 }
39556349Sqs148142 intrp->msi_intx_cnt = nactual;
39566349Sqs148142
39576349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39586349Sqs148142 "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
39596349Sqs148142 navail, nactual, intrp->msi_intx_cnt, intrp->intr_added));
39606349Sqs148142
39616349Sqs148142 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
39626349Sqs148142 (void) hxge_intr_ldgv_init(hxgep);
39636349Sqs148142
39646349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type"));
39656349Sqs148142
39666349Sqs148142 return (status);
39676349Sqs148142 }
39686349Sqs148142
39696349Sqs148142 /*ARGSUSED*/
39706349Sqs148142 static hxge_status_t
hxge_add_intrs_adv_type_fix(p_hxge_t hxgep,uint32_t int_type)39716349Sqs148142 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type)
39726349Sqs148142 {
39736349Sqs148142 dev_info_t *dip = hxgep->dip;
39746349Sqs148142 p_hxge_ldg_t ldgp;
39756349Sqs148142 p_hxge_intr_t intrp;
39766349Sqs148142 uint_t *inthandler;
39776349Sqs148142 void *arg1, *arg2;
39786349Sqs148142 int behavior;
39796349Sqs148142 int nintrs, navail;
39806349Sqs148142 int nactual, nrequired;
39816349Sqs148142 int inum = 0;
39826349Sqs148142 int x, y;
39836349Sqs148142 int ddi_status = DDI_SUCCESS;
39846349Sqs148142 hxge_status_t status = HXGE_OK;
39856349Sqs148142
39866349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix"));
39876349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
39886349Sqs148142
39896349Sqs148142 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
39906349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
39916349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
39926349Sqs148142 "ddi_intr_get_nintrs() failed, status: 0x%x%, "
39936349Sqs148142 "nintrs: %d", status, nintrs));
39946349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
39956349Sqs148142 }
39966349Sqs148142
39976349Sqs148142 ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
39986349Sqs148142 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
39996349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40006349Sqs148142 "ddi_intr_get_navail() failed, status: 0x%x%, "
40016349Sqs148142 "nintrs: %d", ddi_status, navail));
40026349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
40036349Sqs148142 }
40046349Sqs148142
40056349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
40066349Sqs148142 "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
40076349Sqs148142 nintrs, navail));
40086349Sqs148142
40096349Sqs148142 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
40106349Sqs148142 DDI_INTR_ALLOC_NORMAL);
40116349Sqs148142 intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
40126349Sqs148142 intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
40136349Sqs148142 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
40146349Sqs148142 navail, &nactual, behavior);
40156349Sqs148142 if (ddi_status != DDI_SUCCESS || nactual == 0) {
40166349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40176349Sqs148142 " ddi_intr_alloc() failed: %d", ddi_status));
40186349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
40196349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
40206349Sqs148142 }
40216349Sqs148142
40226349Sqs148142 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
40236349Sqs148142 (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
40246349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40256349Sqs148142 " ddi_intr_get_pri() failed: %d", ddi_status));
40266349Sqs148142 /* Free already allocated interrupts */
40276349Sqs148142 for (y = 0; y < nactual; y++) {
40286349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
40296349Sqs148142 }
40306349Sqs148142
40316349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
40326349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
40336349Sqs148142 }
40346349Sqs148142
40356349Sqs148142 nrequired = 0;
40366349Sqs148142 status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
40376349Sqs148142 if (status != HXGE_OK) {
40386349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40396349Sqs148142 "hxge_add_intrs_adv_type_fix:hxge_ldgv_init "
40406349Sqs148142 "failed: 0x%x", status));
40416349Sqs148142 /* Free already allocated interrupts */
40426349Sqs148142 for (y = 0; y < nactual; y++) {
40436349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
40446349Sqs148142 }
40456349Sqs148142
40466349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
40476349Sqs148142 return (status);
40486349Sqs148142 }
40496349Sqs148142
40506349Sqs148142 ldgp = hxgep->ldgvp->ldgp;
40516349Sqs148142 for (x = 0; x < nrequired; x++, ldgp++) {
40526349Sqs148142 ldgp->vector = (uint8_t)x;
40536349Sqs148142 arg1 = ldgp->ldvp;
40546349Sqs148142 arg2 = hxgep;
40556349Sqs148142 if (ldgp->nldvs == 1) {
40566349Sqs148142 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
40576349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
40586349Sqs148142 "hxge_add_intrs_adv_type_fix: "
40596349Sqs148142 "1-1 int handler(%d) ldg %d ldv %d "
40606349Sqs148142 "arg1 $%p arg2 $%p\n",
40616349Sqs148142 x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2));
40626349Sqs148142 } else if (ldgp->nldvs > 1) {
40636349Sqs148142 inthandler = (uint_t *)ldgp->sys_intr_handler;
40646349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
40656349Sqs148142 "hxge_add_intrs_adv_type_fix: "
40666349Sqs148142 "shared ldv %d int handler(%d) ldv %d ldg %d"
40676349Sqs148142 "arg1 0x%016llx arg2 0x%016llx\n",
40686349Sqs148142 x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
40696349Sqs148142 arg1, arg2));
40706349Sqs148142 }
40716349Sqs148142
40726349Sqs148142 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
40736349Sqs148142 (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
40746349Sqs148142 DDI_SUCCESS) {
40756349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40766349Sqs148142 "==> hxge_add_intrs_adv_type_fix: failed #%d "
40776349Sqs148142 "status 0x%x", x, ddi_status));
40786349Sqs148142 for (y = 0; y < intrp->intr_added; y++) {
40796349Sqs148142 (void) ddi_intr_remove_handler(
40806349Sqs148142 intrp->htable[y]);
40816349Sqs148142 }
40826349Sqs148142 for (y = 0; y < nactual; y++) {
40836349Sqs148142 (void) ddi_intr_free(intrp->htable[y]);
40846349Sqs148142 }
40856349Sqs148142 /* Free already allocated intr */
40866349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
40876349Sqs148142
40886349Sqs148142 (void) hxge_ldgv_uninit(hxgep);
40896349Sqs148142
40906349Sqs148142 return (HXGE_ERROR | HXGE_DDI_FAILED);
40916349Sqs148142 }
40926349Sqs148142 intrp->intr_added++;
40936349Sqs148142 }
40946349Sqs148142
40956349Sqs148142 intrp->msi_intx_cnt = nactual;
40966349Sqs148142
40976349Sqs148142 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
40986349Sqs148142
40996349Sqs148142 status = hxge_intr_ldgv_init(hxgep);
41006349Sqs148142
41016349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix"));
41026349Sqs148142
41036349Sqs148142 return (status);
41046349Sqs148142 }
41056349Sqs148142
41066349Sqs148142 /*ARGSUSED*/
41076349Sqs148142 static void
hxge_remove_intrs(p_hxge_t hxgep)41086349Sqs148142 hxge_remove_intrs(p_hxge_t hxgep)
41096349Sqs148142 {
41106349Sqs148142 int i, inum;
41116349Sqs148142 p_hxge_intr_t intrp;
41126349Sqs148142
41136349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs"));
41146349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
41156349Sqs148142 if (!intrp->intr_registered) {
41166349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
41176349Sqs148142 "<== hxge_remove_intrs: interrupts not registered"));
41186349Sqs148142 return;
41196349Sqs148142 }
41206349Sqs148142
41216349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced"));
41226349Sqs148142
41236349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
41246349Sqs148142 (void) ddi_intr_block_disable(intrp->htable,
41256349Sqs148142 intrp->intr_added);
41266349Sqs148142 } else {
41276349Sqs148142 for (i = 0; i < intrp->intr_added; i++) {
41286349Sqs148142 (void) ddi_intr_disable(intrp->htable[i]);
41296349Sqs148142 }
41306349Sqs148142 }
41316349Sqs148142
41326349Sqs148142 for (inum = 0; inum < intrp->intr_added; inum++) {
41336349Sqs148142 if (intrp->htable[inum]) {
41346349Sqs148142 (void) ddi_intr_remove_handler(intrp->htable[inum]);
41356349Sqs148142 }
41366349Sqs148142 }
41376349Sqs148142
41386349Sqs148142 for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
41396349Sqs148142 if (intrp->htable[inum]) {
41406349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
41416349Sqs148142 "hxge_remove_intrs: ddi_intr_free inum %d "
41426349Sqs148142 "msi_intx_cnt %d intr_added %d",
41436349Sqs148142 inum, intrp->msi_intx_cnt, intrp->intr_added));
41446349Sqs148142
41456349Sqs148142 (void) ddi_intr_free(intrp->htable[inum]);
41466349Sqs148142 }
41476349Sqs148142 }
41486349Sqs148142
41496349Sqs148142 kmem_free(intrp->htable, intrp->intr_size);
41506349Sqs148142 intrp->intr_registered = B_FALSE;
41516349Sqs148142 intrp->intr_enabled = B_FALSE;
41526349Sqs148142 intrp->msi_intx_cnt = 0;
41536349Sqs148142 intrp->intr_added = 0;
41546349Sqs148142
41556349Sqs148142 (void) hxge_ldgv_uninit(hxgep);
41566349Sqs148142
41576349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs"));
41586349Sqs148142 }
41596349Sqs148142
41606349Sqs148142 /*ARGSUSED*/
416111257SMichael.Speer@Sun.COM static void
hxge_intrs_enable(p_hxge_t hxgep)41626349Sqs148142 hxge_intrs_enable(p_hxge_t hxgep)
41636349Sqs148142 {
41646349Sqs148142 p_hxge_intr_t intrp;
41656349Sqs148142 int i;
41666349Sqs148142 int status;
41676349Sqs148142
41686349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable"));
41696349Sqs148142
41706349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
41716349Sqs148142
41726349Sqs148142 if (!intrp->intr_registered) {
41736349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: "
41746349Sqs148142 "interrupts are not registered"));
41756349Sqs148142 return;
41766349Sqs148142 }
41776349Sqs148142
41786349Sqs148142 if (intrp->intr_enabled) {
41796349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL,
41806349Sqs148142 "<== hxge_intrs_enable: already enabled"));
41816349Sqs148142 return;
41826349Sqs148142 }
41836349Sqs148142
41846349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
41856349Sqs148142 status = ddi_intr_block_enable(intrp->htable,
41866349Sqs148142 intrp->intr_added);
41876349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
41886349Sqs148142 "block enable - status 0x%x total inums #%d\n",
41896349Sqs148142 status, intrp->intr_added));
41906349Sqs148142 } else {
41916349Sqs148142 for (i = 0; i < intrp->intr_added; i++) {
41926349Sqs148142 status = ddi_intr_enable(intrp->htable[i]);
41936349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
41946349Sqs148142 "ddi_intr_enable:enable - status 0x%x "
41956349Sqs148142 "total inums %d enable inum #%d\n",
41966349Sqs148142 status, intrp->intr_added, i));
41976349Sqs148142 if (status == DDI_SUCCESS) {
41986349Sqs148142 intrp->intr_enabled = B_TRUE;
41996349Sqs148142 }
42006349Sqs148142 }
42016349Sqs148142 }
42026349Sqs148142
42036349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable"));
42046349Sqs148142 }
42056349Sqs148142
42066349Sqs148142 /*ARGSUSED*/
42076349Sqs148142 static void
hxge_intrs_disable(p_hxge_t hxgep)42086349Sqs148142 hxge_intrs_disable(p_hxge_t hxgep)
42096349Sqs148142 {
42106349Sqs148142 p_hxge_intr_t intrp;
42116349Sqs148142 int i;
42126349Sqs148142
42136349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable"));
42146349Sqs148142
42156349Sqs148142 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
42166349Sqs148142
42176349Sqs148142 if (!intrp->intr_registered) {
42186349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: "
42196349Sqs148142 "interrupts are not registered"));
42206349Sqs148142 return;
42216349Sqs148142 }
42226349Sqs148142
42236349Sqs148142 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
42246349Sqs148142 (void) ddi_intr_block_disable(intrp->htable,
42256349Sqs148142 intrp->intr_added);
42266349Sqs148142 } else {
42276349Sqs148142 for (i = 0; i < intrp->intr_added; i++) {
42286349Sqs148142 (void) ddi_intr_disable(intrp->htable[i]);
42296349Sqs148142 }
42306349Sqs148142 }
42316349Sqs148142
42326349Sqs148142 intrp->intr_enabled = B_FALSE;
42336349Sqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable"));
42346349Sqs148142 }
42356349Sqs148142
42366349Sqs148142 static hxge_status_t
hxge_mac_register(p_hxge_t hxgep)42376349Sqs148142 hxge_mac_register(p_hxge_t hxgep)
42386349Sqs148142 {
42396349Sqs148142 mac_register_t *macp;
42406349Sqs148142 int status;
42416349Sqs148142
42426349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register"));
42436349Sqs148142
42446349Sqs148142 if ((macp = mac_alloc(MAC_VERSION)) == NULL)
42456349Sqs148142 return (HXGE_ERROR);
42466349Sqs148142
42476349Sqs148142 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
42486349Sqs148142 macp->m_driver = hxgep;
42496349Sqs148142 macp->m_dip = hxgep->dip;
42506349Sqs148142 macp->m_src_addr = hxgep->ouraddr.ether_addr_octet;
42518718SMichael.Speer@Sun.COM macp->m_callbacks = &hxge_m_callbacks;
42528718SMichael.Speer@Sun.COM macp->m_min_sdu = 0;
42538718SMichael.Speer@Sun.COM macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE;
42548718SMichael.Speer@Sun.COM macp->m_margin = VLAN_TAGSZ;
42558718SMichael.Speer@Sun.COM macp->m_priv_props = hxge_priv_props;
42568718SMichael.Speer@Sun.COM macp->m_v12n = MAC_VIRT_LEVEL1;
42576349Sqs148142
42586349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL,
42596349Sqs148142 "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x",
42606349Sqs148142 macp->m_src_addr[0],
42616349Sqs148142 macp->m_src_addr[1],
42626349Sqs148142 macp->m_src_addr[2],
42636349Sqs148142 macp->m_src_addr[3],
42646349Sqs148142 macp->m_src_addr[4],
42656349Sqs148142 macp->m_src_addr[5]));
42666349Sqs148142
42676349Sqs148142 status = mac_register(macp, &hxgep->mach);
42686349Sqs148142 mac_free(macp);
42696349Sqs148142
42706349Sqs148142 if (status != 0) {
42716349Sqs148142 cmn_err(CE_WARN,
42726349Sqs148142 "hxge_mac_register failed (status %d instance %d)",
42736349Sqs148142 status, hxgep->instance);
42746349Sqs148142 return (HXGE_ERROR);
42756349Sqs148142 }
42766349Sqs148142
42776349Sqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success "
42786349Sqs148142 "(instance %d)", hxgep->instance));
42796349Sqs148142
42806349Sqs148142 return (HXGE_OK);
42816349Sqs148142 }
42826349Sqs148142
42836349Sqs148142 static int
hxge_init_common_dev(p_hxge_t hxgep)42846349Sqs148142 hxge_init_common_dev(p_hxge_t hxgep)
42856349Sqs148142 {
42866349Sqs148142 p_hxge_hw_list_t hw_p;
42876349Sqs148142 dev_info_t *p_dip;
42886349Sqs148142
42896349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev"));
42906349Sqs148142
42916349Sqs148142 p_dip = hxgep->p_dip;
42926349Sqs148142 MUTEX_ENTER(&hxge_common_lock);
42936349Sqs148142
42946349Sqs148142 /*
42956349Sqs148142 * Loop through existing per Hydra hardware list.
42966349Sqs148142 */
42976349Sqs148142 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
42986349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42996349Sqs148142 "==> hxge_init_common_dev: hw_p $%p parent dip $%p",
43006349Sqs148142 hw_p, p_dip));
43016349Sqs148142 if (hw_p->parent_devp == p_dip) {
43026349Sqs148142 hxgep->hxge_hw_p = hw_p;
43036349Sqs148142 hw_p->ndevs++;
43046349Sqs148142 hw_p->hxge_p = hxgep;
43056349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43066349Sqs148142 "==> hxge_init_common_device: "
43076349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (found)",
43086349Sqs148142 hw_p, p_dip, hw_p->ndevs));
43096349Sqs148142 break;
43106349Sqs148142 }
43116349Sqs148142 }
43126349Sqs148142
43136349Sqs148142 if (hw_p == NULL) {
43146349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43156349Sqs148142 "==> hxge_init_common_dev: parent dip $%p (new)", p_dip));
43166349Sqs148142 hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP);
43176349Sqs148142 hw_p->parent_devp = p_dip;
43186349Sqs148142 hw_p->magic = HXGE_MAGIC;
43196349Sqs148142 hxgep->hxge_hw_p = hw_p;
43206349Sqs148142 hw_p->ndevs++;
43216349Sqs148142 hw_p->hxge_p = hxgep;
43226349Sqs148142 hw_p->next = hxge_hw_list;
43236349Sqs148142
43246349Sqs148142 MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
43256349Sqs148142 MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
43266349Sqs148142 MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
43276349Sqs148142
43286349Sqs148142 hxge_hw_list = hw_p;
43296349Sqs148142 }
43306349Sqs148142 MUTEX_EXIT(&hxge_common_lock);
43316349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43326349Sqs148142 "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list));
43336349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev"));
43346349Sqs148142
43356349Sqs148142 return (HXGE_OK);
43366349Sqs148142 }
43376349Sqs148142
43386349Sqs148142 static void
hxge_uninit_common_dev(p_hxge_t hxgep)43396349Sqs148142 hxge_uninit_common_dev(p_hxge_t hxgep)
43406349Sqs148142 {
43416349Sqs148142 p_hxge_hw_list_t hw_p, h_hw_p;
43426349Sqs148142 dev_info_t *p_dip;
43436349Sqs148142
43446349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev"));
43456349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
43466349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43476349Sqs148142 "<== hxge_uninit_common_dev (no common)"));
43486349Sqs148142 return;
43496349Sqs148142 }
43506349Sqs148142
43516349Sqs148142 MUTEX_ENTER(&hxge_common_lock);
43526349Sqs148142 h_hw_p = hxge_hw_list;
43536349Sqs148142 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
43546349Sqs148142 p_dip = hw_p->parent_devp;
43556349Sqs148142 if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip &&
43566349Sqs148142 hxgep->hxge_hw_p->magic == HXGE_MAGIC &&
43576349Sqs148142 hw_p->magic == HXGE_MAGIC) {
43586349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43596349Sqs148142 "==> hxge_uninit_common_dev: "
43606349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (found)",
43616349Sqs148142 hw_p, p_dip, hw_p->ndevs));
43626349Sqs148142
43636349Sqs148142 hxgep->hxge_hw_p = NULL;
43646349Sqs148142 if (hw_p->ndevs) {
43656349Sqs148142 hw_p->ndevs--;
43666349Sqs148142 }
43676349Sqs148142 hw_p->hxge_p = NULL;
43686349Sqs148142 if (!hw_p->ndevs) {
43696349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_vlan_lock);
43706349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_tcam_lock);
43716349Sqs148142 MUTEX_DESTROY(&hw_p->hxge_cfg_lock);
43726349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43736349Sqs148142 "==> hxge_uninit_common_dev: "
43746349Sqs148142 "hw_p $%p parent dip $%p ndevs %d (last)",
43756349Sqs148142 hw_p, p_dip, hw_p->ndevs));
43766349Sqs148142
43776349Sqs148142 if (hw_p == hxge_hw_list) {
43786349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43796349Sqs148142 "==> hxge_uninit_common_dev:"
43806349Sqs148142 "remove head "
43816349Sqs148142 "hw_p $%p parent dip $%p "
43826349Sqs148142 "ndevs %d (head)",
43836349Sqs148142 hw_p, p_dip, hw_p->ndevs));
43846349Sqs148142 hxge_hw_list = hw_p->next;
43856349Sqs148142 } else {
43866349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43876349Sqs148142 "==> hxge_uninit_common_dev:"
43886349Sqs148142 "remove middle "
43896349Sqs148142 "hw_p $%p parent dip $%p "
43906349Sqs148142 "ndevs %d (middle)",
43916349Sqs148142 hw_p, p_dip, hw_p->ndevs));
43926349Sqs148142 h_hw_p->next = hw_p->next;
43936349Sqs148142 }
43946349Sqs148142
43956349Sqs148142 KMEM_FREE(hw_p, sizeof (hxge_hw_list_t));
43966349Sqs148142 }
43976349Sqs148142 break;
43986349Sqs148142 } else {
43996349Sqs148142 h_hw_p = hw_p;
44006349Sqs148142 }
44016349Sqs148142 }
44026349Sqs148142
44036349Sqs148142 MUTEX_EXIT(&hxge_common_lock);
44046349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL,
44056349Sqs148142 "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list));
44066349Sqs148142
44076349Sqs148142 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev"));
44086349Sqs148142 }
44097584SQiyan.Sun@Sun.COM
44108236SQiyan.Sun@Sun.COM #define HXGE_MSIX_ENTRIES 32
44118236SQiyan.Sun@Sun.COM #define HXGE_MSIX_WAIT_COUNT 10
44128236SQiyan.Sun@Sun.COM #define HXGE_MSIX_PARITY_CHECK_COUNT 30
44138236SQiyan.Sun@Sun.COM
44147584SQiyan.Sun@Sun.COM static void
hxge_link_poll(void * arg)44157584SQiyan.Sun@Sun.COM hxge_link_poll(void *arg)
44167584SQiyan.Sun@Sun.COM {
44177584SQiyan.Sun@Sun.COM p_hxge_t hxgep = (p_hxge_t)arg;
44187584SQiyan.Sun@Sun.COM hpi_handle_t handle;
44197584SQiyan.Sun@Sun.COM cip_link_stat_t link_stat;
44207584SQiyan.Sun@Sun.COM hxge_timeout *to = &hxgep->timeout;
44217584SQiyan.Sun@Sun.COM
44227584SQiyan.Sun@Sun.COM handle = HXGE_DEV_HPI_HANDLE(hxgep);
44237584SQiyan.Sun@Sun.COM HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value);
44247584SQiyan.Sun@Sun.COM
44257949SQiyan.Sun@Sun.COM if (to->report_link_status ||
44267949SQiyan.Sun@Sun.COM (to->link_status != link_stat.bits.xpcs0_link_up)) {
44277584SQiyan.Sun@Sun.COM to->link_status = link_stat.bits.xpcs0_link_up;
44287949SQiyan.Sun@Sun.COM to->report_link_status = B_FALSE;
44297584SQiyan.Sun@Sun.COM
44307584SQiyan.Sun@Sun.COM if (link_stat.bits.xpcs0_link_up) {
44317949SQiyan.Sun@Sun.COM hxge_link_update(hxgep, LINK_STATE_UP);
44327584SQiyan.Sun@Sun.COM } else {
44337949SQiyan.Sun@Sun.COM hxge_link_update(hxgep, LINK_STATE_DOWN);
44347584SQiyan.Sun@Sun.COM }
44357584SQiyan.Sun@Sun.COM }
44367584SQiyan.Sun@Sun.COM
44377584SQiyan.Sun@Sun.COM /* Restart the link status timer to check the link status */
44387584SQiyan.Sun@Sun.COM MUTEX_ENTER(&to->lock);
44397584SQiyan.Sun@Sun.COM to->id = timeout(hxge_link_poll, arg, to->ticks);
44407584SQiyan.Sun@Sun.COM MUTEX_EXIT(&to->lock);
44417584SQiyan.Sun@Sun.COM }
44427949SQiyan.Sun@Sun.COM
44437949SQiyan.Sun@Sun.COM static void
hxge_link_update(p_hxge_t hxgep,link_state_t state)44447949SQiyan.Sun@Sun.COM hxge_link_update(p_hxge_t hxgep, link_state_t state)
44457949SQiyan.Sun@Sun.COM {
44467949SQiyan.Sun@Sun.COM p_hxge_stats_t statsp = (p_hxge_stats_t)hxgep->statsp;
44477949SQiyan.Sun@Sun.COM
44487949SQiyan.Sun@Sun.COM mac_link_update(hxgep->mach, state);
44497949SQiyan.Sun@Sun.COM if (state == LINK_STATE_UP) {
44507949SQiyan.Sun@Sun.COM statsp->mac_stats.link_speed = 10000;
44517949SQiyan.Sun@Sun.COM statsp->mac_stats.link_duplex = 2;
44527949SQiyan.Sun@Sun.COM statsp->mac_stats.link_up = 1;
44537949SQiyan.Sun@Sun.COM } else {
44547949SQiyan.Sun@Sun.COM statsp->mac_stats.link_speed = 0;
44557949SQiyan.Sun@Sun.COM statsp->mac_stats.link_duplex = 0;
44567949SQiyan.Sun@Sun.COM statsp->mac_stats.link_up = 0;
44577949SQiyan.Sun@Sun.COM }
44587949SQiyan.Sun@Sun.COM }
44598236SQiyan.Sun@Sun.COM
44608236SQiyan.Sun@Sun.COM static void
hxge_msix_init(p_hxge_t hxgep)44618236SQiyan.Sun@Sun.COM hxge_msix_init(p_hxge_t hxgep)
44628236SQiyan.Sun@Sun.COM {
44638366SQiyan.Sun@Sun.COM uint32_t data0;
44648366SQiyan.Sun@Sun.COM uint32_t data1;
44658366SQiyan.Sun@Sun.COM uint32_t data2;
44668236SQiyan.Sun@Sun.COM int i;
44678366SQiyan.Sun@Sun.COM uint32_t msix_entry0;
44688366SQiyan.Sun@Sun.COM uint32_t msix_entry1;
44698366SQiyan.Sun@Sun.COM uint32_t msix_entry2;
44708366SQiyan.Sun@Sun.COM uint32_t msix_entry3;
44718366SQiyan.Sun@Sun.COM
44728366SQiyan.Sun@Sun.COM /* Change to use MSIx bar instead of indirect access */
44738236SQiyan.Sun@Sun.COM for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
44748366SQiyan.Sun@Sun.COM data0 = 0xffffffff - i;
44758366SQiyan.Sun@Sun.COM data1 = 0xffffffff - i - 1;
44768366SQiyan.Sun@Sun.COM data2 = 0xffffffff - i - 2;
44778366SQiyan.Sun@Sun.COM
44788366SQiyan.Sun@Sun.COM HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16, data0);
44798366SQiyan.Sun@Sun.COM HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 4, data1);
44808366SQiyan.Sun@Sun.COM HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 8, data2);
448111257SMichael.Speer@Sun.COM HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 12, 0);
44828236SQiyan.Sun@Sun.COM }
44838236SQiyan.Sun@Sun.COM
44848366SQiyan.Sun@Sun.COM /* Initialize ram data out buffer. */
44858366SQiyan.Sun@Sun.COM for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
44868366SQiyan.Sun@Sun.COM HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16, &msix_entry0);
44878366SQiyan.Sun@Sun.COM HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 4, &msix_entry1);
44888366SQiyan.Sun@Sun.COM HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 8, &msix_entry2);
44898366SQiyan.Sun@Sun.COM HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 12, &msix_entry3);
44908366SQiyan.Sun@Sun.COM }
44918366SQiyan.Sun@Sun.COM }
44928366SQiyan.Sun@Sun.COM
44938366SQiyan.Sun@Sun.COM /*
44948366SQiyan.Sun@Sun.COM * The following function is to support
44958366SQiyan.Sun@Sun.COM * PSARC/2007/453 MSI-X interrupt limit override.
44968366SQiyan.Sun@Sun.COM */
44978366SQiyan.Sun@Sun.COM static int
hxge_create_msi_property(p_hxge_t hxgep)44988366SQiyan.Sun@Sun.COM hxge_create_msi_property(p_hxge_t hxgep)
44998236SQiyan.Sun@Sun.COM {
45008366SQiyan.Sun@Sun.COM int nmsi;
45018366SQiyan.Sun@Sun.COM extern int ncpus;
45028366SQiyan.Sun@Sun.COM
45038366SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==>hxge_create_msi_property"));
45048366SQiyan.Sun@Sun.COM
45058366SQiyan.Sun@Sun.COM (void) ddi_prop_create(DDI_DEV_T_NONE, hxgep->dip,
45068366SQiyan.Sun@Sun.COM DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
45078366SQiyan.Sun@Sun.COM /*
45088366SQiyan.Sun@Sun.COM * The maximum MSI-X requested will be 8.
45098366SQiyan.Sun@Sun.COM * If the # of CPUs is less than 8, we will reqeust
45108366SQiyan.Sun@Sun.COM * # MSI-X based on the # of CPUs.
45118366SQiyan.Sun@Sun.COM */
45128366SQiyan.Sun@Sun.COM if (ncpus >= HXGE_MSIX_REQUEST_10G) {
45138366SQiyan.Sun@Sun.COM nmsi = HXGE_MSIX_REQUEST_10G;
45148366SQiyan.Sun@Sun.COM } else {
45158366SQiyan.Sun@Sun.COM nmsi = ncpus;
45168236SQiyan.Sun@Sun.COM }
45178236SQiyan.Sun@Sun.COM
45188366SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, MOD_CTL,
45198366SQiyan.Sun@Sun.COM "==>hxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
45208366SQiyan.Sun@Sun.COM ddi_prop_exists(DDI_DEV_T_NONE, hxgep->dip,
45218366SQiyan.Sun@Sun.COM DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
45228366SQiyan.Sun@Sun.COM
45238366SQiyan.Sun@Sun.COM HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<==hxge_create_msi_property"));
45248366SQiyan.Sun@Sun.COM return (nmsi);
45258236SQiyan.Sun@Sun.COM }
4526