xref: /illumos-gate/usr/src/uts/common/io/ena/ena_gld.c (revision c46e4de3)
16f443ebcSRyan Zezeski /*
26f443ebcSRyan Zezeski  * This file and its contents are supplied under the terms of the
36f443ebcSRyan Zezeski  * Common Development and Distribution License ("CDDL"), version 1.0.
46f443ebcSRyan Zezeski  * You may only use this file in accordance with the terms of version
56f443ebcSRyan Zezeski  * 1.0 of the CDDL.
66f443ebcSRyan Zezeski  *
76f443ebcSRyan Zezeski  * A full copy of the text of the CDDL should have accompanied this
86f443ebcSRyan Zezeski  * source.  A copy of the CDDL is also available via the Internet at
96f443ebcSRyan Zezeski  * http://www.illumos.org/license/CDDL.
106f443ebcSRyan Zezeski  */
116f443ebcSRyan Zezeski 
126f443ebcSRyan Zezeski /*
13*c46e4de3SAndy Fiddaman  * Copyright 2024 Oxide Computer Company
146f443ebcSRyan Zezeski  */
15*c46e4de3SAndy Fiddaman 
166f443ebcSRyan Zezeski #include "ena.h"
176f443ebcSRyan Zezeski 
186f443ebcSRyan Zezeski /*
196f443ebcSRyan Zezeski  * Group/Ring callbacks
206f443ebcSRyan Zezeski  */
216f443ebcSRyan Zezeski 
226f443ebcSRyan Zezeski /*
236f443ebcSRyan Zezeski  * The ena driver supports only a single mac address: the one assigned
246f443ebcSRyan Zezeski  * to it by the hypervisor. If mac requests an address besides this
256f443ebcSRyan Zezeski  * one, then return ENOTSUP. This will prevent VNICs from being
266f443ebcSRyan Zezeski  * created, as it should.
276f443ebcSRyan Zezeski  */
286f443ebcSRyan Zezeski static int
ena_group_add_mac(void * arg,const uint8_t * mac_addr)296f443ebcSRyan Zezeski ena_group_add_mac(void *arg, const uint8_t *mac_addr)
306f443ebcSRyan Zezeski {
316f443ebcSRyan Zezeski 	ena_t *ena = arg;
326f443ebcSRyan Zezeski 
336f443ebcSRyan Zezeski 	if (ETHER_IS_MULTICAST(mac_addr)) {
346f443ebcSRyan Zezeski 		return (EINVAL);
356f443ebcSRyan Zezeski 	}
366f443ebcSRyan Zezeski 
376f443ebcSRyan Zezeski 	if (bcmp(ena->ena_mac_addr, mac_addr, ETHERADDRL) == 0) {
386f443ebcSRyan Zezeski 		return (0);
396f443ebcSRyan Zezeski 	}
406f443ebcSRyan Zezeski 
416f443ebcSRyan Zezeski 	return (ENOTSUP);
426f443ebcSRyan Zezeski }
436f443ebcSRyan Zezeski 
446f443ebcSRyan Zezeski static int
ena_group_rem_mac(void * arg,const uint8_t * mac_addr)456f443ebcSRyan Zezeski ena_group_rem_mac(void *arg, const uint8_t *mac_addr)
466f443ebcSRyan Zezeski {
476f443ebcSRyan Zezeski 	ena_t *ena = arg;
486f443ebcSRyan Zezeski 
496f443ebcSRyan Zezeski 	if (ETHER_IS_MULTICAST(mac_addr)) {
506f443ebcSRyan Zezeski 		return (EINVAL);
516f443ebcSRyan Zezeski 	}
526f443ebcSRyan Zezeski 
536f443ebcSRyan Zezeski 	if (bcmp(ena->ena_mac_addr, mac_addr, ETHERADDRL) == 0) {
546f443ebcSRyan Zezeski 		return (0);
556f443ebcSRyan Zezeski 	}
566f443ebcSRyan Zezeski 
576f443ebcSRyan Zezeski 	return (ENOTSUP);
586f443ebcSRyan Zezeski }
596f443ebcSRyan Zezeski 
606f443ebcSRyan Zezeski static int
ena_ring_rx_intr_disable(mac_intr_handle_t mih)616f443ebcSRyan Zezeski ena_ring_rx_intr_disable(mac_intr_handle_t mih)
626f443ebcSRyan Zezeski {
636f443ebcSRyan Zezeski 	ena_rxq_t *rxq = (ena_rxq_t *)mih;
646f443ebcSRyan Zezeski 	uint32_t intr_ctrl;
656f443ebcSRyan Zezeski 
666f443ebcSRyan Zezeski 	mutex_enter(&rxq->er_lock);
676f443ebcSRyan Zezeski 	intr_ctrl = ena_hw_abs_read32(rxq->er_ena, rxq->er_cq_unmask_addr);
686f443ebcSRyan Zezeski 	ENAHW_REG_INTR_MASK(intr_ctrl);
696f443ebcSRyan Zezeski 	ena_hw_abs_write32(rxq->er_ena, rxq->er_cq_unmask_addr, intr_ctrl);
706f443ebcSRyan Zezeski 	rxq->er_mode = ENA_RXQ_MODE_POLLING;
716f443ebcSRyan Zezeski 	mutex_exit(&rxq->er_lock);
726f443ebcSRyan Zezeski 	return (0);
736f443ebcSRyan Zezeski }
746f443ebcSRyan Zezeski 
756f443ebcSRyan Zezeski static int
ena_ring_rx_intr_enable(mac_intr_handle_t mih)766f443ebcSRyan Zezeski ena_ring_rx_intr_enable(mac_intr_handle_t mih)
776f443ebcSRyan Zezeski {
786f443ebcSRyan Zezeski 	ena_rxq_t *rxq = (ena_rxq_t *)mih;
796f443ebcSRyan Zezeski 	uint32_t intr_ctrl;
806f443ebcSRyan Zezeski 
816f443ebcSRyan Zezeski 	mutex_enter(&rxq->er_lock);
826f443ebcSRyan Zezeski 	intr_ctrl = ena_hw_abs_read32(rxq->er_ena, rxq->er_cq_unmask_addr);
836f443ebcSRyan Zezeski 	ENAHW_REG_INTR_UNMASK(intr_ctrl);
846f443ebcSRyan Zezeski 	ena_hw_abs_write32(rxq->er_ena, rxq->er_cq_unmask_addr, intr_ctrl);
856f443ebcSRyan Zezeski 	rxq->er_mode = ENA_RXQ_MODE_INTR;
866f443ebcSRyan Zezeski 	mutex_exit(&rxq->er_lock);
876f443ebcSRyan Zezeski 	return (0);
886f443ebcSRyan Zezeski }
896f443ebcSRyan Zezeski 
906f443ebcSRyan Zezeski static void
ena_fill_rx_group(void * arg,mac_ring_type_t rtype,const int index,mac_group_info_t * infop,mac_group_handle_t gh)916f443ebcSRyan Zezeski ena_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
926f443ebcSRyan Zezeski     mac_group_info_t *infop, mac_group_handle_t gh)
936f443ebcSRyan Zezeski {
946f443ebcSRyan Zezeski 	ena_t *ena = arg;
956f443ebcSRyan Zezeski 
966f443ebcSRyan Zezeski 	VERIFY3S(rtype, ==, MAC_RING_TYPE_RX);
976f443ebcSRyan Zezeski 	/*
986f443ebcSRyan Zezeski 	 * Typically you pass an Rx group data structure as
996f443ebcSRyan Zezeski 	 * mgi_driver, but given we should only ever have one group we
1006f443ebcSRyan Zezeski 	 * just pass the top-level ena_t.
1016f443ebcSRyan Zezeski 	 */
1026f443ebcSRyan Zezeski 	infop->mgi_driver = (mac_group_driver_t)ena;
1036f443ebcSRyan Zezeski 	infop->mgi_start = NULL;
1046f443ebcSRyan Zezeski 	infop->mgi_stop = NULL;
1056f443ebcSRyan Zezeski 	infop->mgi_addmac = ena_group_add_mac;
1066f443ebcSRyan Zezeski 	infop->mgi_remmac = ena_group_rem_mac;
1076f443ebcSRyan Zezeski 	infop->mgi_count = ena->ena_num_intrs - 1;
1086f443ebcSRyan Zezeski }
1096f443ebcSRyan Zezeski 
1106f443ebcSRyan Zezeski static void
ena_fill_tx_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)1116f443ebcSRyan Zezeski ena_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
1126f443ebcSRyan Zezeski     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
1136f443ebcSRyan Zezeski {
1146f443ebcSRyan Zezeski 	ena_t *ena = arg;
115*c46e4de3SAndy Fiddaman 	ena_txq_t *txq = &ena->ena_txqs[ring_index];
1166f443ebcSRyan Zezeski 
1176f443ebcSRyan Zezeski 	VERIFY3S(rtype, ==, MAC_RING_TYPE_TX);
1186f443ebcSRyan Zezeski 	VERIFY3S(ring_index, <, ena->ena_num_txqs);
1196f443ebcSRyan Zezeski 	/* Link driver Tx queue to mac ring handle and vice versa. */
1206f443ebcSRyan Zezeski 	txq->et_mrh = rh;
1216f443ebcSRyan Zezeski 	infop->mri_driver = (mac_ring_driver_t)txq;
1226f443ebcSRyan Zezeski 	infop->mri_start = ena_ring_tx_start;
1236f443ebcSRyan Zezeski 	infop->mri_stop = ena_ring_tx_stop;
1246f443ebcSRyan Zezeski 	infop->mri_tx = ena_ring_tx;
1256f443ebcSRyan Zezeski 	infop->mri_stat = ena_ring_tx_stat;
1266f443ebcSRyan Zezeski }
1276f443ebcSRyan Zezeski 
1286f443ebcSRyan Zezeski static void
ena_fill_rx_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)1296f443ebcSRyan Zezeski ena_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
1306f443ebcSRyan Zezeski     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
1316f443ebcSRyan Zezeski {
1326f443ebcSRyan Zezeski 	ena_t *ena = arg;
133*c46e4de3SAndy Fiddaman 	ena_rxq_t *rxq = &ena->ena_rxqs[ring_index];
1346f443ebcSRyan Zezeski 
1356f443ebcSRyan Zezeski 	VERIFY3S(rtype, ==, MAC_RING_TYPE_RX);
1366f443ebcSRyan Zezeski 	VERIFY3S(ring_index, <, ena->ena_num_rxqs);
1376f443ebcSRyan Zezeski 	rxq->er_mrh = rh;
1386f443ebcSRyan Zezeski 	infop->mri_driver = (mac_ring_driver_t)rxq;
1396f443ebcSRyan Zezeski 	infop->mri_start = ena_ring_rx_start;
1406f443ebcSRyan Zezeski 	infop->mri_stop = ena_ring_rx_stop;
1416f443ebcSRyan Zezeski 	infop->mri_poll = ena_ring_rx_poll;
1426f443ebcSRyan Zezeski 	infop->mri_stat = ena_ring_rx_stat;
1436f443ebcSRyan Zezeski 	infop->mri_intr.mi_handle = (mac_intr_handle_t)rxq;
1446f443ebcSRyan Zezeski 	infop->mri_intr.mi_enable = ena_ring_rx_intr_enable;
1456f443ebcSRyan Zezeski 	infop->mri_intr.mi_disable = ena_ring_rx_intr_disable;
1466f443ebcSRyan Zezeski 	infop->mri_intr.mi_ddi_handle =
1476f443ebcSRyan Zezeski 	    ena->ena_intr_handles[rxq->er_intr_vector];
1486f443ebcSRyan Zezeski }
1496f443ebcSRyan Zezeski 
1506f443ebcSRyan Zezeski static int
ena_m_start(void * arg)1516f443ebcSRyan Zezeski ena_m_start(void *arg)
1526f443ebcSRyan Zezeski {
1536f443ebcSRyan Zezeski 	ena_t *ena = arg;
1546f443ebcSRyan Zezeski 
155*c46e4de3SAndy Fiddaman 	atomic_or_32(&ena->ena_state, ENA_STATE_STARTED);
156*c46e4de3SAndy Fiddaman 	ena_enable_watchdog(ena);
157*c46e4de3SAndy Fiddaman 
1586f443ebcSRyan Zezeski 	return (0);
1596f443ebcSRyan Zezeski }
1606f443ebcSRyan Zezeski 
1616f443ebcSRyan Zezeski static void
ena_m_stop(void * arg)1626f443ebcSRyan Zezeski ena_m_stop(void *arg)
1636f443ebcSRyan Zezeski {
1646f443ebcSRyan Zezeski 	ena_t *ena = arg;
165*c46e4de3SAndy Fiddaman 
166*c46e4de3SAndy Fiddaman 	ena_disable_watchdog(ena);
167*c46e4de3SAndy Fiddaman 	atomic_and_32(&ena->ena_state, ~ENA_STATE_STARTED);
1686f443ebcSRyan Zezeski }
1696f443ebcSRyan Zezeski 
1706f443ebcSRyan Zezeski /*
1716f443ebcSRyan Zezeski  * As discussed in ena_group_add_mac(), ENA only supports a single MAC
1726f443ebcSRyan Zezeski  * address, and therefore we prevent VNICs from being created. That
1736f443ebcSRyan Zezeski  * means there is no chance for promisc to be used as a means for
1746f443ebcSRyan Zezeski  * implementing VNIC support on ENA, as we never allow them to be
1756f443ebcSRyan Zezeski  * created in the first place.
1766f443ebcSRyan Zezeski  *
1776f443ebcSRyan Zezeski  * As for promisc itself, returning success is about the best we can
1786f443ebcSRyan Zezeski  * do. There is no promisc API for an ENA device -- you get only the
1796f443ebcSRyan Zezeski  * exact traffic AWS wants you to see.
1806f443ebcSRyan Zezeski  */
1816f443ebcSRyan Zezeski static int
ena_m_setpromisc(void * arg,boolean_t on)1826f443ebcSRyan Zezeski ena_m_setpromisc(void *arg, boolean_t on)
1836f443ebcSRyan Zezeski {
1846f443ebcSRyan Zezeski 	return (0);
1856f443ebcSRyan Zezeski }
1866f443ebcSRyan Zezeski 
1876f443ebcSRyan Zezeski /*
1886f443ebcSRyan Zezeski  * Similarly to promisc, there is no multicast API for an ENA
1896f443ebcSRyan Zezeski  * device.
1906f443ebcSRyan Zezeski  */
1916f443ebcSRyan Zezeski static int
ena_m_multicast(void * arg,boolean_t add,const uint8_t * multicast_address)1926f443ebcSRyan Zezeski ena_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
1936f443ebcSRyan Zezeski {
1946f443ebcSRyan Zezeski 	return (0);
1956f443ebcSRyan Zezeski }
1966f443ebcSRyan Zezeski 
1976f443ebcSRyan Zezeski static boolean_t
ena_m_getcapab(void * arg,mac_capab_t capab,void * cap_data)1986f443ebcSRyan Zezeski ena_m_getcapab(void *arg, mac_capab_t capab, void *cap_data)
1996f443ebcSRyan Zezeski {
2006f443ebcSRyan Zezeski 	ena_t *ena = arg;
2016f443ebcSRyan Zezeski 	mac_capab_rings_t *cap_rings;
2026f443ebcSRyan Zezeski 
2036f443ebcSRyan Zezeski 	switch (capab) {
2046f443ebcSRyan Zezeski 	case MAC_CAPAB_RINGS:
2056f443ebcSRyan Zezeski 		cap_rings = cap_data;
2066f443ebcSRyan Zezeski 		cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
2076f443ebcSRyan Zezeski 		cap_rings->mr_gaddring = NULL;
2086f443ebcSRyan Zezeski 		cap_rings->mr_gremring = NULL;
2096f443ebcSRyan Zezeski 		ASSERT3U(ena->ena_num_intrs, >=, 2);
2106f443ebcSRyan Zezeski 
2116f443ebcSRyan Zezeski 		switch (cap_rings->mr_type) {
2126f443ebcSRyan Zezeski 		case MAC_RING_TYPE_TX:
2136f443ebcSRyan Zezeski 			/*
2146f443ebcSRyan Zezeski 			 * We use pseudo Tx groups for now.
2156f443ebcSRyan Zezeski 			 */
2166f443ebcSRyan Zezeski 			cap_rings->mr_gnum = 0;
2176f443ebcSRyan Zezeski 			cap_rings->mr_rnum = ena->ena_num_intrs - 1;
2186f443ebcSRyan Zezeski 			cap_rings->mr_rget = ena_fill_tx_ring;
2196f443ebcSRyan Zezeski 			break;
2206f443ebcSRyan Zezeski 		case MAC_RING_TYPE_RX:
2216f443ebcSRyan Zezeski 			cap_rings->mr_rnum = ena->ena_num_intrs - 1;
2226f443ebcSRyan Zezeski 			cap_rings->mr_rget = ena_fill_rx_ring;
2236f443ebcSRyan Zezeski 			/*
2246f443ebcSRyan Zezeski 			 * The ENA device provides no means to add mac
2256f443ebcSRyan Zezeski 			 * filters or set promisc mode; it's only
2266f443ebcSRyan Zezeski 			 * meant to receive its pre-designated unicast
2276f443ebcSRyan Zezeski 			 * address. However, we still want rings as
2286f443ebcSRyan Zezeski 			 * the device does provide multiple queues and
2296f443ebcSRyan Zezeski 			 * RSS.
2306f443ebcSRyan Zezeski 			 */
2316f443ebcSRyan Zezeski 			cap_rings->mr_gnum = 1;
2326f443ebcSRyan Zezeski 			cap_rings->mr_gget = ena_fill_rx_group;
2336f443ebcSRyan Zezeski 			break;
2346f443ebcSRyan Zezeski 		}
2356f443ebcSRyan Zezeski 
2366f443ebcSRyan Zezeski 		break;
2376f443ebcSRyan Zezeski 
2386f443ebcSRyan Zezeski 	case MAC_CAPAB_HCKSUM:
2396f443ebcSRyan Zezeski 	case MAC_CAPAB_LSO:
2406f443ebcSRyan Zezeski 		return (B_FALSE);
2416f443ebcSRyan Zezeski 	default:
2426f443ebcSRyan Zezeski 		return (B_FALSE);
2436f443ebcSRyan Zezeski 	}
2446f443ebcSRyan Zezeski 
2456f443ebcSRyan Zezeski 	return (B_TRUE);
2466f443ebcSRyan Zezeski }
2476f443ebcSRyan Zezeski 
2486f443ebcSRyan Zezeski static int
ena_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)2496f443ebcSRyan Zezeski ena_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2506f443ebcSRyan Zezeski     uint_t pr_valsize, const void *pr_val)
2516f443ebcSRyan Zezeski {
2526f443ebcSRyan Zezeski 	return (ENOTSUP);
2536f443ebcSRyan Zezeski }
2546f443ebcSRyan Zezeski 
2556f443ebcSRyan Zezeski static int
ena_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)2566f443ebcSRyan Zezeski ena_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2576f443ebcSRyan Zezeski     uint_t pr_valsize, void *pr_val)
2586f443ebcSRyan Zezeski {
2596f443ebcSRyan Zezeski 	ena_t *ena = arg;
2606f443ebcSRyan Zezeski 	int ret = 0;
2616f443ebcSRyan Zezeski 	uint64_t speed;
2626f443ebcSRyan Zezeski 	uint8_t *u8;
2636f443ebcSRyan Zezeski 
2646f443ebcSRyan Zezeski 	mutex_enter(&ena->ena_lock);
2656f443ebcSRyan Zezeski 
2666f443ebcSRyan Zezeski 	switch (pr_num) {
2676f443ebcSRyan Zezeski 	case MAC_PROP_DUPLEX:
2686f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (link_duplex_t)) {
2696f443ebcSRyan Zezeski 			ret = EOVERFLOW;
2706f443ebcSRyan Zezeski 			break;
2716f443ebcSRyan Zezeski 		}
2726f443ebcSRyan Zezeski 
2736f443ebcSRyan Zezeski 		bcopy(&ena->ena_link_duplex, pr_val, sizeof (link_duplex_t));
2746f443ebcSRyan Zezeski 		break;
2756f443ebcSRyan Zezeski 
2766f443ebcSRyan Zezeski 	case MAC_PROP_SPEED:
2776f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint64_t)) {
2786f443ebcSRyan Zezeski 			ret = EOVERFLOW;
2796f443ebcSRyan Zezeski 			break;
2806f443ebcSRyan Zezeski 		}
2816f443ebcSRyan Zezeski 
2826f443ebcSRyan Zezeski 		speed = ena->ena_link_speed_mbits * 1000000ULL;
2836f443ebcSRyan Zezeski 		bcopy(&speed, pr_val, sizeof (speed));
2846f443ebcSRyan Zezeski 		break;
2856f443ebcSRyan Zezeski 
2866f443ebcSRyan Zezeski 	case MAC_PROP_STATUS:
2876f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (link_state_t)) {
2886f443ebcSRyan Zezeski 			ret = EOVERFLOW;
2896f443ebcSRyan Zezeski 			break;
2906f443ebcSRyan Zezeski 		}
2916f443ebcSRyan Zezeski 
2926f443ebcSRyan Zezeski 		bcopy(&ena->ena_link_state, pr_val, sizeof (link_state_t));
2936f443ebcSRyan Zezeski 		break;
2946f443ebcSRyan Zezeski 
2956f443ebcSRyan Zezeski 	case MAC_PROP_AUTONEG:
2966f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
2976f443ebcSRyan Zezeski 			ret = EOVERFLOW;
2986f443ebcSRyan Zezeski 			break;
2996f443ebcSRyan Zezeski 		}
3006f443ebcSRyan Zezeski 
3016f443ebcSRyan Zezeski 		u8 = pr_val;
3026f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_autoneg ? 0 : 1);
3036f443ebcSRyan Zezeski 		break;
3046f443ebcSRyan Zezeski 
3056f443ebcSRyan Zezeski 	case MAC_PROP_MTU:
3066f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint32_t)) {
3076f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3086f443ebcSRyan Zezeski 			break;
3096f443ebcSRyan Zezeski 		}
3106f443ebcSRyan Zezeski 
3116f443ebcSRyan Zezeski 		bcopy(&ena->ena_mtu, pr_val, sizeof (uint32_t));
3126f443ebcSRyan Zezeski 		break;
3136f443ebcSRyan Zezeski 
3146f443ebcSRyan Zezeski 	case MAC_PROP_ADV_1000FDX_CAP:
3156f443ebcSRyan Zezeski 	case MAC_PROP_EN_1000FDX_CAP:
3166f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3176f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3186f443ebcSRyan Zezeski 			break;
3196f443ebcSRyan Zezeski 		}
3206f443ebcSRyan Zezeski 
3216f443ebcSRyan Zezeski 		u8 = pr_val;
3226f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_1G) != 0;
3236f443ebcSRyan Zezeski 		break;
3246f443ebcSRyan Zezeski 
3256f443ebcSRyan Zezeski 	case MAC_PROP_ADV_2500FDX_CAP:
3266f443ebcSRyan Zezeski 	case MAC_PROP_EN_2500FDX_CAP:
3276f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3286f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3296f443ebcSRyan Zezeski 			break;
3306f443ebcSRyan Zezeski 		}
3316f443ebcSRyan Zezeski 
3326f443ebcSRyan Zezeski 		u8 = pr_val;
3336f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_2_HALF_G) != 0;
3346f443ebcSRyan Zezeski 		break;
3356f443ebcSRyan Zezeski 
3366f443ebcSRyan Zezeski 	case MAC_PROP_ADV_5000FDX_CAP:
3376f443ebcSRyan Zezeski 	case MAC_PROP_EN_5000FDX_CAP:
3386f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3396f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3406f443ebcSRyan Zezeski 			break;
3416f443ebcSRyan Zezeski 		}
3426f443ebcSRyan Zezeski 
3436f443ebcSRyan Zezeski 		u8 = pr_val;
3446f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_5G) != 0;
3456f443ebcSRyan Zezeski 		break;
3466f443ebcSRyan Zezeski 
3476f443ebcSRyan Zezeski 	case MAC_PROP_ADV_10GFDX_CAP:
3486f443ebcSRyan Zezeski 	case MAC_PROP_EN_10GFDX_CAP:
3496f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3506f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3516f443ebcSRyan Zezeski 			break;
3526f443ebcSRyan Zezeski 		}
3536f443ebcSRyan Zezeski 
3546f443ebcSRyan Zezeski 		u8 = pr_val;
3556f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_10G) != 0;
3566f443ebcSRyan Zezeski 		break;
3576f443ebcSRyan Zezeski 
3586f443ebcSRyan Zezeski 	case MAC_PROP_ADV_25GFDX_CAP:
3596f443ebcSRyan Zezeski 	case MAC_PROP_EN_25GFDX_CAP:
3606f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3616f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3626f443ebcSRyan Zezeski 			break;
3636f443ebcSRyan Zezeski 		}
3646f443ebcSRyan Zezeski 
3656f443ebcSRyan Zezeski 		u8 = pr_val;
3666f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_25G) != 0;
3676f443ebcSRyan Zezeski 		break;
3686f443ebcSRyan Zezeski 
3696f443ebcSRyan Zezeski 	case MAC_PROP_ADV_40GFDX_CAP:
3706f443ebcSRyan Zezeski 	case MAC_PROP_EN_40GFDX_CAP:
3716f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3726f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3736f443ebcSRyan Zezeski 			break;
3746f443ebcSRyan Zezeski 		}
3756f443ebcSRyan Zezeski 
3766f443ebcSRyan Zezeski 		u8 = pr_val;
3776f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_40G) != 0;
3786f443ebcSRyan Zezeski 		break;
3796f443ebcSRyan Zezeski 
3806f443ebcSRyan Zezeski 	case MAC_PROP_ADV_100GFDX_CAP:
3816f443ebcSRyan Zezeski 	case MAC_PROP_EN_100GFDX_CAP:
3826f443ebcSRyan Zezeski 		if (pr_valsize < sizeof (uint8_t)) {
3836f443ebcSRyan Zezeski 			ret = EOVERFLOW;
3846f443ebcSRyan Zezeski 			break;
3856f443ebcSRyan Zezeski 		}
3866f443ebcSRyan Zezeski 
3876f443ebcSRyan Zezeski 		u8 = pr_val;
3886f443ebcSRyan Zezeski 		*u8 = (ena->ena_link_speeds & ENAHW_LINK_SPEED_100G) != 0;
3896f443ebcSRyan Zezeski 		break;
3906f443ebcSRyan Zezeski 
3916f443ebcSRyan Zezeski 	default:
3926f443ebcSRyan Zezeski 		ret = ENOTSUP;
3936f443ebcSRyan Zezeski 		break;
3946f443ebcSRyan Zezeski 	}
3956f443ebcSRyan Zezeski 
3966f443ebcSRyan Zezeski 	mutex_exit(&ena->ena_lock);
3976f443ebcSRyan Zezeski 	return (ret);
3986f443ebcSRyan Zezeski }
3996f443ebcSRyan Zezeski 
4006f443ebcSRyan Zezeski static void
ena_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)4016f443ebcSRyan Zezeski ena_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
4026f443ebcSRyan Zezeski     mac_prop_info_handle_t prh)
4036f443ebcSRyan Zezeski {
4046f443ebcSRyan Zezeski }
4056f443ebcSRyan Zezeski 
4066f443ebcSRyan Zezeski static mac_callbacks_t ena_m_callbacks = {
4076f443ebcSRyan Zezeski 	.mc_callbacks = MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
4086f443ebcSRyan Zezeski 	.mc_getstat = ena_m_stat,
4096f443ebcSRyan Zezeski 	.mc_start = ena_m_start,
4106f443ebcSRyan Zezeski 	.mc_stop = ena_m_stop,
4116f443ebcSRyan Zezeski 	.mc_setpromisc = ena_m_setpromisc,
4126f443ebcSRyan Zezeski 	.mc_multicst = ena_m_multicast,
4136f443ebcSRyan Zezeski 	.mc_getcapab = ena_m_getcapab,
4146f443ebcSRyan Zezeski 	.mc_setprop = ena_m_setprop,
4156f443ebcSRyan Zezeski 	.mc_getprop = ena_m_getprop,
4166f443ebcSRyan Zezeski 	.mc_propinfo = ena_m_propinfo,
4176f443ebcSRyan Zezeski };
4186f443ebcSRyan Zezeski 
4196f443ebcSRyan Zezeski int
ena_mac_unregister(ena_t * ena)4206f443ebcSRyan Zezeski ena_mac_unregister(ena_t *ena)
4216f443ebcSRyan Zezeski {
4226f443ebcSRyan Zezeski 	if (ena->ena_mh == NULL) {
4236f443ebcSRyan Zezeski 		return (0);
4246f443ebcSRyan Zezeski 	}
4256f443ebcSRyan Zezeski 
4266f443ebcSRyan Zezeski 	return (mac_unregister(ena->ena_mh));
4276f443ebcSRyan Zezeski }
4286f443ebcSRyan Zezeski 
429*c46e4de3SAndy Fiddaman bool
ena_mac_register(ena_t * ena)4306f443ebcSRyan Zezeski ena_mac_register(ena_t *ena)
4316f443ebcSRyan Zezeski {
4326f443ebcSRyan Zezeski 	int ret;
4336f443ebcSRyan Zezeski 	mac_register_t *regp;
4346f443ebcSRyan Zezeski 
4356f443ebcSRyan Zezeski 	if ((regp = mac_alloc(MAC_VERSION)) == NULL) {
4366f443ebcSRyan Zezeski 		ena_err(ena, "failed to allocate MAC handle");
437*c46e4de3SAndy Fiddaman 		return (false);
4386f443ebcSRyan Zezeski 	}
4396f443ebcSRyan Zezeski 
4406f443ebcSRyan Zezeski 	regp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
4416f443ebcSRyan Zezeski 	regp->m_driver = ena;
4426f443ebcSRyan Zezeski 	regp->m_dip = ena->ena_dip;
4436f443ebcSRyan Zezeski 	regp->m_instance = 0;
4446f443ebcSRyan Zezeski 	regp->m_src_addr = ena->ena_mac_addr;
4456f443ebcSRyan Zezeski 	regp->m_dst_addr = NULL;
4466f443ebcSRyan Zezeski 	regp->m_callbacks = &ena_m_callbacks;
4476f443ebcSRyan Zezeski 	regp->m_min_sdu = 0;
4486f443ebcSRyan Zezeski 	regp->m_max_sdu = ena->ena_mtu;
4496f443ebcSRyan Zezeski 	regp->m_pdata = NULL;
4506f443ebcSRyan Zezeski 	regp->m_pdata_size = 0;
4516f443ebcSRyan Zezeski 	regp->m_priv_props = NULL;
4526f443ebcSRyan Zezeski 	regp->m_margin = VLAN_TAGSZ;
4536f443ebcSRyan Zezeski 	regp->m_v12n = MAC_VIRT_LEVEL1;
4546f443ebcSRyan Zezeski 
4556f443ebcSRyan Zezeski 	if ((ret = mac_register(regp, &ena->ena_mh)) != 0) {
4566f443ebcSRyan Zezeski 		ena_err(ena, "failed to register ena with mac: %d", ret);
4576f443ebcSRyan Zezeski 	}
4586f443ebcSRyan Zezeski 
4596f443ebcSRyan Zezeski 	mac_free(regp);
4606f443ebcSRyan Zezeski 
4616f443ebcSRyan Zezeski 	if (ret == 0) {
4626f443ebcSRyan Zezeski 		/*
4636f443ebcSRyan Zezeski 		 * Until we get the first AENQ link change event, we
4646f443ebcSRyan Zezeski 		 * do not actually know the status of the link.
4656f443ebcSRyan Zezeski 		 */
4666f443ebcSRyan Zezeski 		mac_link_update(ena->ena_mh, LINK_STATE_UNKNOWN);
4676f443ebcSRyan Zezeski 	}
4686f443ebcSRyan Zezeski 
4696f443ebcSRyan Zezeski 	return (ret == 0);
4706f443ebcSRyan Zezeski }
471