xref: /illumos-gate/usr/src/uts/common/io/i40e/i40e_gld.c (revision 338749cb)
19d26e4fcSRobert Mustacchi /*
29d26e4fcSRobert Mustacchi  * This file and its contents are supplied under the terms of the
39d26e4fcSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
49d26e4fcSRobert Mustacchi  * You may only use this file in accordance with the terms of version
59d26e4fcSRobert Mustacchi  * 1.0 of the CDDL.
69d26e4fcSRobert Mustacchi  *
79d26e4fcSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
89d26e4fcSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
99d26e4fcSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
109d26e4fcSRobert Mustacchi  */
119d26e4fcSRobert Mustacchi 
129d26e4fcSRobert Mustacchi /*
139d26e4fcSRobert Mustacchi  * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
14*338749cbSRobert Mustacchi  * Copyright (c) 2017, Joyent, Inc.
15396505afSPaul Winder  * Copyright 2017 Tegile Systems, Inc.  All rights reserved.
169d26e4fcSRobert Mustacchi  */
179d26e4fcSRobert Mustacchi 
189d26e4fcSRobert Mustacchi /*
199d26e4fcSRobert Mustacchi  * For more information, please see the big theory statement in i40e_main.c.
209d26e4fcSRobert Mustacchi  */
219d26e4fcSRobert Mustacchi 
229d26e4fcSRobert Mustacchi #include "i40e_sw.h"
239d26e4fcSRobert Mustacchi 
249d26e4fcSRobert Mustacchi #define	I40E_PROP_RX_DMA_THRESH	"_rx_dma_threshold"
259d26e4fcSRobert Mustacchi #define	I40E_PROP_TX_DMA_THRESH	"_tx_dma_threshold"
269d26e4fcSRobert Mustacchi #define	I40E_PROP_RX_ITR	"_rx_intr_throttle"
279d26e4fcSRobert Mustacchi #define	I40E_PROP_TX_ITR	"_tx_intr_throttle"
289d26e4fcSRobert Mustacchi #define	I40E_PROP_OTHER_ITR	"_other_intr_throttle"
299d26e4fcSRobert Mustacchi 
309d26e4fcSRobert Mustacchi char *i40e_priv_props[] = {
319d26e4fcSRobert Mustacchi 	I40E_PROP_RX_DMA_THRESH,
329d26e4fcSRobert Mustacchi 	I40E_PROP_TX_DMA_THRESH,
339d26e4fcSRobert Mustacchi 	I40E_PROP_RX_ITR,
349d26e4fcSRobert Mustacchi 	I40E_PROP_TX_ITR,
359d26e4fcSRobert Mustacchi 	I40E_PROP_OTHER_ITR,
369d26e4fcSRobert Mustacchi 	NULL
379d26e4fcSRobert Mustacchi };
389d26e4fcSRobert Mustacchi 
399d26e4fcSRobert Mustacchi static int
409d26e4fcSRobert Mustacchi i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
419d26e4fcSRobert Mustacchi {
429d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
439d26e4fcSRobert Mustacchi 	struct i40e_aqc_remove_macvlan_element_data filt;
449d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
459d26e4fcSRobert Mustacchi 	int ret, i, last;
469d26e4fcSRobert Mustacchi 	i40e_uaddr_t *iua;
479d26e4fcSRobert Mustacchi 
489d26e4fcSRobert Mustacchi 	if (I40E_IS_MULTICAST(mac_addr))
499d26e4fcSRobert Mustacchi 		return (EINVAL);
509d26e4fcSRobert Mustacchi 
519d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
529d26e4fcSRobert Mustacchi 
539d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
549d26e4fcSRobert Mustacchi 		ret = ECANCELED;
559d26e4fcSRobert Mustacchi 		goto done;
569d26e4fcSRobert Mustacchi 	}
579d26e4fcSRobert Mustacchi 
589d26e4fcSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
599d26e4fcSRobert Mustacchi 		if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
609d26e4fcSRobert Mustacchi 		    ETHERADDRL) == 0)
619d26e4fcSRobert Mustacchi 			break;
629d26e4fcSRobert Mustacchi 	}
639d26e4fcSRobert Mustacchi 
649d26e4fcSRobert Mustacchi 	if (i == i40e->i40e_resources.ifr_nmacfilt_used) {
659d26e4fcSRobert Mustacchi 		ret = ENOENT;
669d26e4fcSRobert Mustacchi 		goto done;
679d26e4fcSRobert Mustacchi 	}
689d26e4fcSRobert Mustacchi 
699d26e4fcSRobert Mustacchi 	iua = &i40e->i40e_uaddrs[i];
709d26e4fcSRobert Mustacchi 	ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0);
719d26e4fcSRobert Mustacchi 
729d26e4fcSRobert Mustacchi 	bzero(&filt, sizeof (filt));
739d26e4fcSRobert Mustacchi 	bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
749d26e4fcSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
759d26e4fcSRobert Mustacchi 	    I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
769d26e4fcSRobert Mustacchi 
779d26e4fcSRobert Mustacchi 	if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) !=
789d26e4fcSRobert Mustacchi 	    I40E_SUCCESS) {
799d26e4fcSRobert Mustacchi 		i40e_error(i40e, "failed to remove mac address "
809d26e4fcSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
819d26e4fcSRobert Mustacchi 		    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
829d26e4fcSRobert Mustacchi 		    mac_addr[4], mac_addr[5], filt.error_code);
839d26e4fcSRobert Mustacchi 		ret = EIO;
849d26e4fcSRobert Mustacchi 		goto done;
859d26e4fcSRobert Mustacchi 	}
869d26e4fcSRobert Mustacchi 
879d26e4fcSRobert Mustacchi 	last = i40e->i40e_resources.ifr_nmacfilt_used - 1;
889d26e4fcSRobert Mustacchi 	if (i != last) {
899d26e4fcSRobert Mustacchi 		i40e_uaddr_t *src = &i40e->i40e_uaddrs[last];
909d26e4fcSRobert Mustacchi 		bcopy(src, iua, sizeof (i40e_uaddr_t));
919d26e4fcSRobert Mustacchi 	}
929d26e4fcSRobert Mustacchi 
939d26e4fcSRobert Mustacchi 	/*
949d26e4fcSRobert Mustacchi 	 * Set the multicast bit in the last one to indicate to ourselves that
959d26e4fcSRobert Mustacchi 	 * it's invalid.
969d26e4fcSRobert Mustacchi 	 */
979d26e4fcSRobert Mustacchi 	bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t));
989d26e4fcSRobert Mustacchi 	i40e->i40e_uaddrs[last].iua_mac[0] = 0x01;
999d26e4fcSRobert Mustacchi 	i40e->i40e_resources.ifr_nmacfilt_used--;
1009d26e4fcSRobert Mustacchi 	ret = 0;
1019d26e4fcSRobert Mustacchi done:
1029d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1039d26e4fcSRobert Mustacchi 
1049d26e4fcSRobert Mustacchi 	return (ret);
1059d26e4fcSRobert Mustacchi }
1069d26e4fcSRobert Mustacchi 
1079d26e4fcSRobert Mustacchi static int
1089d26e4fcSRobert Mustacchi i40e_group_add_mac(void *arg, const uint8_t *mac_addr)
1099d26e4fcSRobert Mustacchi {
1109d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
1119d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
1129d26e4fcSRobert Mustacchi 	int i, ret;
1139d26e4fcSRobert Mustacchi 	i40e_uaddr_t *iua;
1149d26e4fcSRobert Mustacchi 	struct i40e_aqc_add_macvlan_element_data filt;
1159d26e4fcSRobert Mustacchi 
1169d26e4fcSRobert Mustacchi 	if (I40E_IS_MULTICAST(mac_addr))
1179d26e4fcSRobert Mustacchi 		return (EINVAL);
1189d26e4fcSRobert Mustacchi 
1199d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
1209d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
1219d26e4fcSRobert Mustacchi 		ret = ECANCELED;
1229d26e4fcSRobert Mustacchi 		goto done;
1239d26e4fcSRobert Mustacchi 	}
1249d26e4fcSRobert Mustacchi 
1259d26e4fcSRobert Mustacchi 	if (i40e->i40e_resources.ifr_nmacfilt ==
1269d26e4fcSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmacfilt_used) {
1279d26e4fcSRobert Mustacchi 		ret = ENOSPC;
1289d26e4fcSRobert Mustacchi 		goto done;
1299d26e4fcSRobert Mustacchi 	}
1309d26e4fcSRobert Mustacchi 
1319d26e4fcSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
1329d26e4fcSRobert Mustacchi 		if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
1339d26e4fcSRobert Mustacchi 		    ETHERADDRL) == 0) {
1349d26e4fcSRobert Mustacchi 			ret = EEXIST;
1359d26e4fcSRobert Mustacchi 			goto done;
1369d26e4fcSRobert Mustacchi 		}
1379d26e4fcSRobert Mustacchi 	}
1389d26e4fcSRobert Mustacchi 
1399d26e4fcSRobert Mustacchi 	/*
1409d26e4fcSRobert Mustacchi 	 * Note, the general use of the i40e_vsi_id will have to be refactored
1419d26e4fcSRobert Mustacchi 	 * when we have proper group support.
1429d26e4fcSRobert Mustacchi 	 */
1439d26e4fcSRobert Mustacchi 	bzero(&filt, sizeof (filt));
1449d26e4fcSRobert Mustacchi 	bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
1459d26e4fcSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH	|
1469d26e4fcSRobert Mustacchi 	    I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
1479d26e4fcSRobert Mustacchi 
1489d26e4fcSRobert Mustacchi 	if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
1499d26e4fcSRobert Mustacchi 	    NULL)) != I40E_SUCCESS) {
1509d26e4fcSRobert Mustacchi 		i40e_error(i40e, "failed to add mac address "
1519d26e4fcSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
1529d26e4fcSRobert Mustacchi 		    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
1539d26e4fcSRobert Mustacchi 		    mac_addr[4], mac_addr[5], ret);
1549d26e4fcSRobert Mustacchi 		ret = EIO;
1559d26e4fcSRobert Mustacchi 		goto done;
1569d26e4fcSRobert Mustacchi 	}
1579d26e4fcSRobert Mustacchi 
1589d26e4fcSRobert Mustacchi 	iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used];
1599d26e4fcSRobert Mustacchi 	bcopy(mac_addr, iua->iua_mac, ETHERADDRL);
1609d26e4fcSRobert Mustacchi 	iua->iua_vsi = i40e->i40e_vsi_id;
1619d26e4fcSRobert Mustacchi 	i40e->i40e_resources.ifr_nmacfilt_used++;
1629d26e4fcSRobert Mustacchi 	ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <=
1639d26e4fcSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmacfilt);
1649d26e4fcSRobert Mustacchi 	ret = 0;
1659d26e4fcSRobert Mustacchi done:
1669d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1679d26e4fcSRobert Mustacchi 	return (ret);
1689d26e4fcSRobert Mustacchi }
1699d26e4fcSRobert Mustacchi 
1709d26e4fcSRobert Mustacchi static int
1719d26e4fcSRobert Mustacchi i40e_m_start(void *arg)
1729d26e4fcSRobert Mustacchi {
1739d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
1749d26e4fcSRobert Mustacchi 	int rc = 0;
1759d26e4fcSRobert Mustacchi 
1769d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
1779d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
1789d26e4fcSRobert Mustacchi 		rc = ECANCELED;
1799d26e4fcSRobert Mustacchi 		goto done;
1809d26e4fcSRobert Mustacchi 	}
1819d26e4fcSRobert Mustacchi 
1829d26e4fcSRobert Mustacchi 	if (!i40e_start(i40e, B_TRUE)) {
1839d26e4fcSRobert Mustacchi 		rc = EIO;
1849d26e4fcSRobert Mustacchi 		goto done;
1859d26e4fcSRobert Mustacchi 	}
1869d26e4fcSRobert Mustacchi 
1879d26e4fcSRobert Mustacchi 	atomic_or_32(&i40e->i40e_state, I40E_STARTED);
1889d26e4fcSRobert Mustacchi done:
1899d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1909d26e4fcSRobert Mustacchi 
1919d26e4fcSRobert Mustacchi 	return (rc);
1929d26e4fcSRobert Mustacchi }
1939d26e4fcSRobert Mustacchi 
1949d26e4fcSRobert Mustacchi static void
1959d26e4fcSRobert Mustacchi i40e_m_stop(void *arg)
1969d26e4fcSRobert Mustacchi {
1979d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
1989d26e4fcSRobert Mustacchi 
1999d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
2009d26e4fcSRobert Mustacchi 
2019d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED)
2029d26e4fcSRobert Mustacchi 		goto done;
2039d26e4fcSRobert Mustacchi 
2049d26e4fcSRobert Mustacchi 	atomic_and_32(&i40e->i40e_state, ~I40E_STARTED);
2059d26e4fcSRobert Mustacchi 	i40e_stop(i40e, B_TRUE);
2069d26e4fcSRobert Mustacchi done:
2079d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
2089d26e4fcSRobert Mustacchi }
2099d26e4fcSRobert Mustacchi 
2109d26e4fcSRobert Mustacchi /*
2119d26e4fcSRobert Mustacchi  * Enable and disable promiscuous mode as requested. We have to toggle both
2129d26e4fcSRobert Mustacchi  * unicast and multicast. Note that multicast may already be enabled due to the
2139d26e4fcSRobert Mustacchi  * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
2149d26e4fcSRobert Mustacchi  * on this.
2159d26e4fcSRobert Mustacchi  */
2169d26e4fcSRobert Mustacchi static int
2179d26e4fcSRobert Mustacchi i40e_m_promisc(void *arg, boolean_t on)
2189d26e4fcSRobert Mustacchi {
2199d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
2209d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
2219d26e4fcSRobert Mustacchi 	int ret = 0, err = 0;
2229d26e4fcSRobert Mustacchi 
2239d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
2249d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
2259d26e4fcSRobert Mustacchi 		ret = ECANCELED;
2269d26e4fcSRobert Mustacchi 		goto done;
2279d26e4fcSRobert Mustacchi 	}
2289d26e4fcSRobert Mustacchi 
2299d26e4fcSRobert Mustacchi 
2309d26e4fcSRobert Mustacchi 	ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
2313d75a287SRobert Mustacchi 	    on, NULL, B_FALSE);
2329d26e4fcSRobert Mustacchi 	if (ret != I40E_SUCCESS) {
2339d26e4fcSRobert Mustacchi 		i40e_error(i40e, "failed to %s unicast promiscuity on "
2349d26e4fcSRobert Mustacchi 		    "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
2359d26e4fcSRobert Mustacchi 		    ret);
2369d26e4fcSRobert Mustacchi 		err = EIO;
2379d26e4fcSRobert Mustacchi 		goto done;
2389d26e4fcSRobert Mustacchi 	}
2399d26e4fcSRobert Mustacchi 
2409d26e4fcSRobert Mustacchi 	/*
2419d26e4fcSRobert Mustacchi 	 * If we have a non-zero mcast_promisc_count, then it has already been
2429d26e4fcSRobert Mustacchi 	 * enabled or we need to leave it that way and not touch it.
2439d26e4fcSRobert Mustacchi 	 */
2449d26e4fcSRobert Mustacchi 	if (i40e->i40e_mcast_promisc_count > 0) {
2459d26e4fcSRobert Mustacchi 		i40e->i40e_promisc_on = on;
2469d26e4fcSRobert Mustacchi 		goto done;
2479d26e4fcSRobert Mustacchi 	}
2489d26e4fcSRobert Mustacchi 
2499d26e4fcSRobert Mustacchi 	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, i40e->i40e_vsi_id,
2509d26e4fcSRobert Mustacchi 	    on, NULL);
2519d26e4fcSRobert Mustacchi 	if (ret != I40E_SUCCESS) {
2529d26e4fcSRobert Mustacchi 		i40e_error(i40e, "failed to %s multicast promiscuity on "
2539d26e4fcSRobert Mustacchi 		    "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
2549d26e4fcSRobert Mustacchi 		    ret);
2559d26e4fcSRobert Mustacchi 
2569d26e4fcSRobert Mustacchi 		/*
2579d26e4fcSRobert Mustacchi 		 * Try our best to put us back into a state that MAC expects us
2589d26e4fcSRobert Mustacchi 		 * to be in.
2599d26e4fcSRobert Mustacchi 		 */
2609d26e4fcSRobert Mustacchi 		ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
2613d75a287SRobert Mustacchi 		    !on, NULL, B_FALSE);
2629d26e4fcSRobert Mustacchi 		if (ret != I40E_SUCCESS) {
2639d26e4fcSRobert Mustacchi 			i40e_error(i40e, "failed to %s unicast promiscuity on "
2649d26e4fcSRobert Mustacchi 			    "the default VSI after toggling multicast failed: "
2659d26e4fcSRobert Mustacchi 			    "%d", on == B_TRUE ? "disable" : "enable", ret);
2669d26e4fcSRobert Mustacchi 		}
2679d26e4fcSRobert Mustacchi 
2689d26e4fcSRobert Mustacchi 		err = EIO;
2699d26e4fcSRobert Mustacchi 		goto done;
2709d26e4fcSRobert Mustacchi 	} else {
2719d26e4fcSRobert Mustacchi 		i40e->i40e_promisc_on = on;
2729d26e4fcSRobert Mustacchi 	}
2739d26e4fcSRobert Mustacchi 
2749d26e4fcSRobert Mustacchi done:
2759d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
2769d26e4fcSRobert Mustacchi 	return (err);
2779d26e4fcSRobert Mustacchi }
2789d26e4fcSRobert Mustacchi 
2799d26e4fcSRobert Mustacchi /*
2809d26e4fcSRobert Mustacchi  * See the big theory statement in i40e_main.c for multicast address management.
2819d26e4fcSRobert Mustacchi  */
2829d26e4fcSRobert Mustacchi static int
2839d26e4fcSRobert Mustacchi i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address)
2849d26e4fcSRobert Mustacchi {
2859d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
2869d26e4fcSRobert Mustacchi 	struct i40e_aqc_add_macvlan_element_data filt;
2879d26e4fcSRobert Mustacchi 	i40e_maddr_t *mc;
2889d26e4fcSRobert Mustacchi 	int ret;
2899d26e4fcSRobert Mustacchi 
2909d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
2919d26e4fcSRobert Mustacchi 
2929d26e4fcSRobert Mustacchi 	if (i40e->i40e_resources.ifr_nmcastfilt_used ==
2939d26e4fcSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmcastfilt) {
2949d26e4fcSRobert Mustacchi 		if (i40e->i40e_mcast_promisc_count == 0 &&
2959d26e4fcSRobert Mustacchi 		    i40e->i40e_promisc_on == B_FALSE) {
2969d26e4fcSRobert Mustacchi 			ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
2979d26e4fcSRobert Mustacchi 			    i40e->i40e_vsi_id, B_TRUE, NULL);
2989d26e4fcSRobert Mustacchi 			if (ret != I40E_SUCCESS) {
2999d26e4fcSRobert Mustacchi 				i40e_error(i40e, "failed to enable multicast "
3009d26e4fcSRobert Mustacchi 				    "promiscuous mode on VSI %d: %d",
3019d26e4fcSRobert Mustacchi 				    i40e->i40e_vsi_id, ret);
3029d26e4fcSRobert Mustacchi 				return (EIO);
3039d26e4fcSRobert Mustacchi 			}
3049d26e4fcSRobert Mustacchi 		}
3059d26e4fcSRobert Mustacchi 		i40e->i40e_mcast_promisc_count++;
3069d26e4fcSRobert Mustacchi 		return (0);
3079d26e4fcSRobert Mustacchi 	}
3089d26e4fcSRobert Mustacchi 
3099d26e4fcSRobert Mustacchi 	mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used];
3109d26e4fcSRobert Mustacchi 	bzero(&filt, sizeof (filt));
3119d26e4fcSRobert Mustacchi 	bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
3129d26e4fcSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |
3139d26e4fcSRobert Mustacchi 	    I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
3149d26e4fcSRobert Mustacchi 
3159d26e4fcSRobert Mustacchi 	if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
3169d26e4fcSRobert Mustacchi 	    NULL)) != I40E_SUCCESS) {
3179d26e4fcSRobert Mustacchi 		i40e_error(i40e, "failed to add mac address "
3189d26e4fcSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
3199d26e4fcSRobert Mustacchi 		    multicast_address[0], multicast_address[1],
3209d26e4fcSRobert Mustacchi 		    multicast_address[2], multicast_address[3],
3219d26e4fcSRobert Mustacchi 		    multicast_address[4], multicast_address[5],
3229d26e4fcSRobert Mustacchi 		    ret);
3239d26e4fcSRobert Mustacchi 		return (EIO);
3249d26e4fcSRobert Mustacchi 	}
3259d26e4fcSRobert Mustacchi 
3269d26e4fcSRobert Mustacchi 	bcopy(multicast_address, mc->ima_mac, ETHERADDRL);
3279d26e4fcSRobert Mustacchi 	i40e->i40e_resources.ifr_nmcastfilt_used++;
3289d26e4fcSRobert Mustacchi 	return (0);
3299d26e4fcSRobert Mustacchi }
3309d26e4fcSRobert Mustacchi 
3319d26e4fcSRobert Mustacchi /*
3329d26e4fcSRobert Mustacchi  * See the big theory statement in i40e_main.c for multicast address management.
3339d26e4fcSRobert Mustacchi  */
3349d26e4fcSRobert Mustacchi static int
3359d26e4fcSRobert Mustacchi i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address)
3369d26e4fcSRobert Mustacchi {
3379d26e4fcSRobert Mustacchi 	int i, ret;
3389d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
3399d26e4fcSRobert Mustacchi 
3409d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
3419d26e4fcSRobert Mustacchi 
3429d26e4fcSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) {
3439d26e4fcSRobert Mustacchi 		struct i40e_aqc_remove_macvlan_element_data filt;
3449d26e4fcSRobert Mustacchi 		int last;
3459d26e4fcSRobert Mustacchi 
3469d26e4fcSRobert Mustacchi 		if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac,
3479d26e4fcSRobert Mustacchi 		    ETHERADDRL) != 0) {
3489d26e4fcSRobert Mustacchi 			continue;
3499d26e4fcSRobert Mustacchi 		}
3509d26e4fcSRobert Mustacchi 
3519d26e4fcSRobert Mustacchi 		bzero(&filt, sizeof (filt));
3529d26e4fcSRobert Mustacchi 		bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
3539d26e4fcSRobert Mustacchi 		filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |
3549d26e4fcSRobert Mustacchi 		    I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
3559d26e4fcSRobert Mustacchi 
3569d26e4fcSRobert Mustacchi 		if (i40e_aq_remove_macvlan(hw, i40e->i40e_vsi_id,
3579d26e4fcSRobert Mustacchi 		    &filt, 1, NULL) != I40E_SUCCESS) {
3589d26e4fcSRobert Mustacchi 			i40e_error(i40e, "failed to remove mac address "
3599d26e4fcSRobert Mustacchi 			    "%2x:%2x:%2x:%2x:%2x:%2x from multicast "
3609d26e4fcSRobert Mustacchi 			    "filter: %d",
3619d26e4fcSRobert Mustacchi 			    multicast_address[0], multicast_address[1],
3629d26e4fcSRobert Mustacchi 			    multicast_address[2], multicast_address[3],
3639d26e4fcSRobert Mustacchi 			    multicast_address[4], multicast_address[5],
3649d26e4fcSRobert Mustacchi 			    filt.error_code);
3659d26e4fcSRobert Mustacchi 			return (EIO);
3669d26e4fcSRobert Mustacchi 		}
3679d26e4fcSRobert Mustacchi 
3689d26e4fcSRobert Mustacchi 		last = i40e->i40e_resources.ifr_nmcastfilt_used - 1;
3699d26e4fcSRobert Mustacchi 		if (i != last) {
3709d26e4fcSRobert Mustacchi 			bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i],
3719d26e4fcSRobert Mustacchi 			    sizeof (i40e_maddr_t));
3729d26e4fcSRobert Mustacchi 			bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t));
3739d26e4fcSRobert Mustacchi 		}
3749d26e4fcSRobert Mustacchi 
3759d26e4fcSRobert Mustacchi 		ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0);
3769d26e4fcSRobert Mustacchi 		i40e->i40e_resources.ifr_nmcastfilt_used--;
3779d26e4fcSRobert Mustacchi 		return (0);
3789d26e4fcSRobert Mustacchi 	}
3799d26e4fcSRobert Mustacchi 
3809d26e4fcSRobert Mustacchi 	if (i40e->i40e_mcast_promisc_count > 0) {
3819d26e4fcSRobert Mustacchi 		if (i40e->i40e_mcast_promisc_count == 1 &&
3829d26e4fcSRobert Mustacchi 		    i40e->i40e_promisc_on == B_FALSE) {
3839d26e4fcSRobert Mustacchi 			ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
3849d26e4fcSRobert Mustacchi 			    i40e->i40e_vsi_id, B_FALSE, NULL);
3859d26e4fcSRobert Mustacchi 			if (ret != I40E_SUCCESS) {
3869d26e4fcSRobert Mustacchi 				i40e_error(i40e, "failed to disable "
3879d26e4fcSRobert Mustacchi 				    "multicast promiscuous mode on VSI %d: %d",
3889d26e4fcSRobert Mustacchi 				    i40e->i40e_vsi_id, ret);
3899d26e4fcSRobert Mustacchi 				return (EIO);
3909d26e4fcSRobert Mustacchi 			}
3919d26e4fcSRobert Mustacchi 		}
3929d26e4fcSRobert Mustacchi 		i40e->i40e_mcast_promisc_count--;
3939d26e4fcSRobert Mustacchi 
3949d26e4fcSRobert Mustacchi 		return (0);
3959d26e4fcSRobert Mustacchi 	}
3969d26e4fcSRobert Mustacchi 
3979d26e4fcSRobert Mustacchi 	return (ENOENT);
3989d26e4fcSRobert Mustacchi }
3999d26e4fcSRobert Mustacchi 
4009d26e4fcSRobert Mustacchi static int
4019d26e4fcSRobert Mustacchi i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
4029d26e4fcSRobert Mustacchi {
4039d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
4049d26e4fcSRobert Mustacchi 	int rc;
4059d26e4fcSRobert Mustacchi 
4069d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
4079d26e4fcSRobert Mustacchi 
4089d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
4099d26e4fcSRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
4109d26e4fcSRobert Mustacchi 		return (ECANCELED);
4119d26e4fcSRobert Mustacchi 	}
4129d26e4fcSRobert Mustacchi 
4139d26e4fcSRobert Mustacchi 	if (add == B_TRUE) {
4149d26e4fcSRobert Mustacchi 		rc = i40e_multicast_add(i40e, multicast_address);
4159d26e4fcSRobert Mustacchi 	} else {
4169d26e4fcSRobert Mustacchi 		rc = i40e_multicast_remove(i40e, multicast_address);
4179d26e4fcSRobert Mustacchi 	}
4189d26e4fcSRobert Mustacchi 
4199d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
4209d26e4fcSRobert Mustacchi 	return (rc);
4219d26e4fcSRobert Mustacchi }
4229d26e4fcSRobert Mustacchi 
4239d26e4fcSRobert Mustacchi /* ARGSUSED */
4249d26e4fcSRobert Mustacchi static void
4259d26e4fcSRobert Mustacchi i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
4269d26e4fcSRobert Mustacchi {
4279d26e4fcSRobert Mustacchi 	/*
4289d26e4fcSRobert Mustacchi 	 * At this time, we don't support toggling i40e into loopback mode. It's
4299d26e4fcSRobert Mustacchi 	 * questionable how much value this has when there's no clear way to
4309d26e4fcSRobert Mustacchi 	 * toggle this behavior from a supported way in userland.
4319d26e4fcSRobert Mustacchi 	 */
4329d26e4fcSRobert Mustacchi 	miocnak(q, mp, 0, EINVAL);
4339d26e4fcSRobert Mustacchi }
4349d26e4fcSRobert Mustacchi 
4359d26e4fcSRobert Mustacchi static int
4369d26e4fcSRobert Mustacchi i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num)
4379d26e4fcSRobert Mustacchi {
4389d26e4fcSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
4399d26e4fcSRobert Mustacchi 
4409d26e4fcSRobert Mustacchi 	/*
4419d26e4fcSRobert Mustacchi 	 * GLDv3 requires we keep track of a generation number, as it uses
4429d26e4fcSRobert Mustacchi 	 * that number to keep track of whether or not a ring is active.
4439d26e4fcSRobert Mustacchi 	 */
4449d26e4fcSRobert Mustacchi 	mutex_enter(&itrq->itrq_rx_lock);
4459d26e4fcSRobert Mustacchi 	itrq->itrq_rxgen = gen_num;
4469d26e4fcSRobert Mustacchi 	mutex_exit(&itrq->itrq_rx_lock);
4479d26e4fcSRobert Mustacchi 	return (0);
4489d26e4fcSRobert Mustacchi }
4499d26e4fcSRobert Mustacchi 
4509d26e4fcSRobert Mustacchi /* ARGSUSED */
4519d26e4fcSRobert Mustacchi static int
4529d26e4fcSRobert Mustacchi i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)
4539d26e4fcSRobert Mustacchi {
4549d26e4fcSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
4559d26e4fcSRobert Mustacchi 
456396505afSPaul Winder 	mutex_enter(&itrq->itrq_rx_lock);
457396505afSPaul Winder 	ASSERT(itrq->itrq_intr_poll == B_TRUE);
458*338749cbSRobert Mustacchi 	i40e_intr_rx_queue_enable(itrq);
459396505afSPaul Winder 	itrq->itrq_intr_poll = B_FALSE;
460396505afSPaul Winder 	mutex_exit(&itrq->itrq_rx_lock);
4619d26e4fcSRobert Mustacchi 
4629d26e4fcSRobert Mustacchi 	return (0);
4639d26e4fcSRobert Mustacchi }
4649d26e4fcSRobert Mustacchi 
4659d26e4fcSRobert Mustacchi /* ARGSUSED */
4669d26e4fcSRobert Mustacchi static int
4679d26e4fcSRobert Mustacchi i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)
4689d26e4fcSRobert Mustacchi {
4699d26e4fcSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
4709d26e4fcSRobert Mustacchi 
471396505afSPaul Winder 	mutex_enter(&itrq->itrq_rx_lock);
472*338749cbSRobert Mustacchi 	i40e_intr_rx_queue_disable(itrq);
473396505afSPaul Winder 	itrq->itrq_intr_poll = B_TRUE;
474396505afSPaul Winder 	mutex_exit(&itrq->itrq_rx_lock);
4759d26e4fcSRobert Mustacchi 
4769d26e4fcSRobert Mustacchi 	return (0);
4779d26e4fcSRobert Mustacchi }
4789d26e4fcSRobert Mustacchi 
4799d26e4fcSRobert Mustacchi /* ARGSUSED */
4809d26e4fcSRobert Mustacchi static void
4819d26e4fcSRobert Mustacchi i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
4829d26e4fcSRobert Mustacchi     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
4839d26e4fcSRobert Mustacchi {
4849d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
4859d26e4fcSRobert Mustacchi 	mac_intr_t *mintr = &infop->mri_intr;
4869d26e4fcSRobert Mustacchi 	i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]);
4879d26e4fcSRobert Mustacchi 
4889d26e4fcSRobert Mustacchi 	/*
4899d26e4fcSRobert Mustacchi 	 * Note the group index here is expected to be -1 due to the fact that
4909d26e4fcSRobert Mustacchi 	 * we're not actually grouping things tx-wise at this time.
4919d26e4fcSRobert Mustacchi 	 */
4929d26e4fcSRobert Mustacchi 	ASSERT(group_index == -1);
4939d26e4fcSRobert Mustacchi 	ASSERT(ring_index < i40e->i40e_num_trqpairs);
4949d26e4fcSRobert Mustacchi 
4959d26e4fcSRobert Mustacchi 	itrq->itrq_mactxring = rh;
4969d26e4fcSRobert Mustacchi 	infop->mri_driver = (mac_ring_driver_t)itrq;
4979d26e4fcSRobert Mustacchi 	infop->mri_start = NULL;
4989d26e4fcSRobert Mustacchi 	infop->mri_stop = NULL;
4999d26e4fcSRobert Mustacchi 	infop->mri_tx = i40e_ring_tx;
5009d26e4fcSRobert Mustacchi 	infop->mri_stat = i40e_tx_ring_stat;
5019d26e4fcSRobert Mustacchi 
5029d26e4fcSRobert Mustacchi 	/*
5039d26e4fcSRobert Mustacchi 	 * We only provide the handle in cases where we have MSI-X interrupts,
5049d26e4fcSRobert Mustacchi 	 * to indicate that we'd actually support retargetting.
5059d26e4fcSRobert Mustacchi 	 */
5069d26e4fcSRobert Mustacchi 	if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
5079d26e4fcSRobert Mustacchi 		mintr->mi_ddi_handle =
5089d26e4fcSRobert Mustacchi 		    i40e->i40e_intr_handles[itrq->itrq_tx_intrvec];
5099d26e4fcSRobert Mustacchi 	}
5109d26e4fcSRobert Mustacchi }
5119d26e4fcSRobert Mustacchi 
5129d26e4fcSRobert Mustacchi /* ARGSUSED */
5139d26e4fcSRobert Mustacchi static void
5149d26e4fcSRobert Mustacchi i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
5159d26e4fcSRobert Mustacchi     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
5169d26e4fcSRobert Mustacchi {
5179d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
5189d26e4fcSRobert Mustacchi 	mac_intr_t *mintr = &infop->mri_intr;
5199d26e4fcSRobert Mustacchi 	i40e_trqpair_t *itrq = &i40e->i40e_trqpairs[ring_index];
5209d26e4fcSRobert Mustacchi 
5219d26e4fcSRobert Mustacchi 	/*
5229d26e4fcSRobert Mustacchi 	 * We assert the group number and ring index to help sanity check
5239d26e4fcSRobert Mustacchi 	 * ourselves and mark that we'll need to rework this when we have
5249d26e4fcSRobert Mustacchi 	 * multiple groups.
5259d26e4fcSRobert Mustacchi 	 */
5269d26e4fcSRobert Mustacchi 	ASSERT3S(group_index, ==, 0);
5279d26e4fcSRobert Mustacchi 	ASSERT3S(ring_index, <, i40e->i40e_num_trqpairs);
5289d26e4fcSRobert Mustacchi 
5299d26e4fcSRobert Mustacchi 	itrq->itrq_macrxring = rh;
5309d26e4fcSRobert Mustacchi 	infop->mri_driver = (mac_ring_driver_t)itrq;
5319d26e4fcSRobert Mustacchi 	infop->mri_start = i40e_ring_start;
5329d26e4fcSRobert Mustacchi 	infop->mri_stop = NULL;
5339d26e4fcSRobert Mustacchi 	infop->mri_poll = i40e_ring_rx_poll;
5349d26e4fcSRobert Mustacchi 	infop->mri_stat = i40e_rx_ring_stat;
5359d26e4fcSRobert Mustacchi 	mintr->mi_handle = (mac_intr_handle_t)itrq;
5369d26e4fcSRobert Mustacchi 	mintr->mi_enable = i40e_rx_ring_intr_enable;
5379d26e4fcSRobert Mustacchi 	mintr->mi_disable = i40e_rx_ring_intr_disable;
5389d26e4fcSRobert Mustacchi 
5399d26e4fcSRobert Mustacchi 	/*
5409d26e4fcSRobert Mustacchi 	 * We only provide the handle in cases where we have MSI-X interrupts,
5419d26e4fcSRobert Mustacchi 	 * to indicate that we'd actually support retargetting.
5429d26e4fcSRobert Mustacchi 	 */
5439d26e4fcSRobert Mustacchi 	if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
5449d26e4fcSRobert Mustacchi 		mintr->mi_ddi_handle =
5459d26e4fcSRobert Mustacchi 		    i40e->i40e_intr_handles[itrq->itrq_rx_intrvec];
5469d26e4fcSRobert Mustacchi 	}
5479d26e4fcSRobert Mustacchi }
5489d26e4fcSRobert Mustacchi 
5499d26e4fcSRobert Mustacchi /* ARGSUSED */
5509d26e4fcSRobert Mustacchi static void
5519d26e4fcSRobert Mustacchi i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
5529d26e4fcSRobert Mustacchi     mac_group_info_t *infop, mac_group_handle_t gh)
5539d26e4fcSRobert Mustacchi {
5549d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
5559d26e4fcSRobert Mustacchi 
5569d26e4fcSRobert Mustacchi 	if (rtype != MAC_RING_TYPE_RX)
5579d26e4fcSRobert Mustacchi 		return;
5589d26e4fcSRobert Mustacchi 
5599d26e4fcSRobert Mustacchi 	/*
5609d26e4fcSRobert Mustacchi 	 * Note, this is a simplified view of a group, given that we only have a
5619d26e4fcSRobert Mustacchi 	 * single group and a single ring at the moment. We'll want to expand
5629d26e4fcSRobert Mustacchi 	 * upon this as we leverage more hardware functionality.
5639d26e4fcSRobert Mustacchi 	 */
5649d26e4fcSRobert Mustacchi 	i40e->i40e_rx_group_handle = gh;
5659d26e4fcSRobert Mustacchi 	infop->mgi_driver = (mac_group_driver_t)i40e;
5669d26e4fcSRobert Mustacchi 	infop->mgi_start = NULL;
5679d26e4fcSRobert Mustacchi 	infop->mgi_stop = NULL;
5689d26e4fcSRobert Mustacchi 	infop->mgi_addmac = i40e_group_add_mac;
5699d26e4fcSRobert Mustacchi 	infop->mgi_remmac = i40e_group_remove_mac;
5709d26e4fcSRobert Mustacchi 
5719d26e4fcSRobert Mustacchi 	ASSERT(i40e->i40e_num_rx_groups == I40E_GROUP_MAX);
5729d26e4fcSRobert Mustacchi 	infop->mgi_count = i40e->i40e_num_trqpairs;
5739d26e4fcSRobert Mustacchi }
5749d26e4fcSRobert Mustacchi 
5759d26e4fcSRobert Mustacchi static boolean_t
5769d26e4fcSRobert Mustacchi i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
5779d26e4fcSRobert Mustacchi {
5789d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
5799d26e4fcSRobert Mustacchi 	mac_capab_rings_t *cap_rings;
5809d26e4fcSRobert Mustacchi 
5819d26e4fcSRobert Mustacchi 	switch (cap) {
5829d26e4fcSRobert Mustacchi 	case MAC_CAPAB_HCKSUM: {
5839d26e4fcSRobert Mustacchi 		uint32_t *txflags = cap_data;
5849d26e4fcSRobert Mustacchi 
5859d26e4fcSRobert Mustacchi 		*txflags = 0;
5869d26e4fcSRobert Mustacchi 		if (i40e->i40e_tx_hcksum_enable == B_TRUE)
5879d26e4fcSRobert Mustacchi 			*txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
5889d26e4fcSRobert Mustacchi 		break;
5899d26e4fcSRobert Mustacchi 	}
5909d26e4fcSRobert Mustacchi 
5919d26e4fcSRobert Mustacchi 	case MAC_CAPAB_RINGS:
5929d26e4fcSRobert Mustacchi 		cap_rings = cap_data;
5939d26e4fcSRobert Mustacchi 		cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
5949d26e4fcSRobert Mustacchi 		switch (cap_rings->mr_type) {
5959d26e4fcSRobert Mustacchi 		case MAC_RING_TYPE_TX:
5969d26e4fcSRobert Mustacchi 			/*
5979d26e4fcSRobert Mustacchi 			 * Note, saying we have no rings, but some number of
5989d26e4fcSRobert Mustacchi 			 * groups indicates to MAC that it should create
5999d26e4fcSRobert Mustacchi 			 * psuedo-groups with one for each TX ring. This may not
6009d26e4fcSRobert Mustacchi 			 * be the long term behavior we want, but it'll work for
6019d26e4fcSRobert Mustacchi 			 * now.
6029d26e4fcSRobert Mustacchi 			 */
6039d26e4fcSRobert Mustacchi 			cap_rings->mr_gnum = 0;
6049d26e4fcSRobert Mustacchi 			cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
6059d26e4fcSRobert Mustacchi 			cap_rings->mr_rget = i40e_fill_tx_ring;
6069d26e4fcSRobert Mustacchi 			cap_rings->mr_gget = NULL;
6079d26e4fcSRobert Mustacchi 			cap_rings->mr_gaddring = NULL;
6089d26e4fcSRobert Mustacchi 			cap_rings->mr_gremring = NULL;
6099d26e4fcSRobert Mustacchi 			break;
6109d26e4fcSRobert Mustacchi 		case MAC_RING_TYPE_RX:
6119d26e4fcSRobert Mustacchi 			cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
6129d26e4fcSRobert Mustacchi 			cap_rings->mr_rget = i40e_fill_rx_ring;
6139d26e4fcSRobert Mustacchi 			cap_rings->mr_gnum = I40E_GROUP_MAX;
6149d26e4fcSRobert Mustacchi 			cap_rings->mr_gget = i40e_fill_rx_group;
6159d26e4fcSRobert Mustacchi 			cap_rings->mr_gaddring = NULL;
6169d26e4fcSRobert Mustacchi 			cap_rings->mr_gremring = NULL;
6179d26e4fcSRobert Mustacchi 			break;
6189d26e4fcSRobert Mustacchi 		default:
6199d26e4fcSRobert Mustacchi 			return (B_FALSE);
6209d26e4fcSRobert Mustacchi 		}
6219d26e4fcSRobert Mustacchi 		break;
6229d26e4fcSRobert Mustacchi 	default:
6239d26e4fcSRobert Mustacchi 		return (B_FALSE);
6249d26e4fcSRobert Mustacchi 	}
6259d26e4fcSRobert Mustacchi 
6269d26e4fcSRobert Mustacchi 	return (B_TRUE);
6279d26e4fcSRobert Mustacchi }
6289d26e4fcSRobert Mustacchi 
6299d26e4fcSRobert Mustacchi /* ARGSUSED */
6309d26e4fcSRobert Mustacchi static int
6319d26e4fcSRobert Mustacchi i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
6329d26e4fcSRobert Mustacchi     const void *pr_val)
6339d26e4fcSRobert Mustacchi {
6349d26e4fcSRobert Mustacchi 	int ret;
6359d26e4fcSRobert Mustacchi 	long val;
6369d26e4fcSRobert Mustacchi 	char *eptr;
6379d26e4fcSRobert Mustacchi 
6389d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
6399d26e4fcSRobert Mustacchi 
6409d26e4fcSRobert Mustacchi 	if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
6419d26e4fcSRobert Mustacchi 	    *eptr != '\0') {
6429d26e4fcSRobert Mustacchi 		return (ret);
6439d26e4fcSRobert Mustacchi 	}
6449d26e4fcSRobert Mustacchi 
6459d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
6469d26e4fcSRobert Mustacchi 		if (val < I40E_MIN_RX_DMA_THRESH ||
6479d26e4fcSRobert Mustacchi 		    val > I40E_MAX_RX_DMA_THRESH) {
6489d26e4fcSRobert Mustacchi 			return (EINVAL);
6499d26e4fcSRobert Mustacchi 		}
6509d26e4fcSRobert Mustacchi 		i40e->i40e_rx_dma_min = (uint32_t)val;
6519d26e4fcSRobert Mustacchi 		return (0);
6529d26e4fcSRobert Mustacchi 	}
6539d26e4fcSRobert Mustacchi 
6549d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
6559d26e4fcSRobert Mustacchi 		if (val < I40E_MIN_TX_DMA_THRESH ||
6569d26e4fcSRobert Mustacchi 		    val > I40E_MAX_TX_DMA_THRESH) {
6579d26e4fcSRobert Mustacchi 			return (EINVAL);
6589d26e4fcSRobert Mustacchi 		}
6599d26e4fcSRobert Mustacchi 		i40e->i40e_tx_dma_min = (uint32_t)val;
6609d26e4fcSRobert Mustacchi 		return (0);
6619d26e4fcSRobert Mustacchi 	}
6629d26e4fcSRobert Mustacchi 
6639d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
6649d26e4fcSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
6659d26e4fcSRobert Mustacchi 		    val > I40E_MAX_ITR) {
6669d26e4fcSRobert Mustacchi 			return (EINVAL);
6679d26e4fcSRobert Mustacchi 		}
6689d26e4fcSRobert Mustacchi 		i40e->i40e_rx_itr = (uint32_t)val;
6699d26e4fcSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
6709d26e4fcSRobert Mustacchi 		return (0);
6719d26e4fcSRobert Mustacchi 	}
6729d26e4fcSRobert Mustacchi 
6739d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
6749d26e4fcSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
6759d26e4fcSRobert Mustacchi 		    val > I40E_MAX_ITR) {
6769d26e4fcSRobert Mustacchi 			return (EINVAL);
6779d26e4fcSRobert Mustacchi 		}
6789d26e4fcSRobert Mustacchi 		i40e->i40e_tx_itr = (uint32_t)val;
6799d26e4fcSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
6809d26e4fcSRobert Mustacchi 		return (0);
6819d26e4fcSRobert Mustacchi 	}
6829d26e4fcSRobert Mustacchi 
6839d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
6849d26e4fcSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
6859d26e4fcSRobert Mustacchi 		    val > I40E_MAX_ITR) {
6869d26e4fcSRobert Mustacchi 			return (EINVAL);
6879d26e4fcSRobert Mustacchi 		}
6889d26e4fcSRobert Mustacchi 		i40e->i40e_tx_itr = (uint32_t)val;
6899d26e4fcSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
6909d26e4fcSRobert Mustacchi 		    i40e->i40e_other_itr);
6919d26e4fcSRobert Mustacchi 		return (0);
6929d26e4fcSRobert Mustacchi 	}
6939d26e4fcSRobert Mustacchi 
6949d26e4fcSRobert Mustacchi 	return (ENOTSUP);
6959d26e4fcSRobert Mustacchi }
6969d26e4fcSRobert Mustacchi 
6979d26e4fcSRobert Mustacchi static int
6989d26e4fcSRobert Mustacchi i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
6999d26e4fcSRobert Mustacchi     void *pr_val)
7009d26e4fcSRobert Mustacchi {
7019d26e4fcSRobert Mustacchi 	uint32_t val;
7029d26e4fcSRobert Mustacchi 
7039d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
7049d26e4fcSRobert Mustacchi 
7059d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
7069d26e4fcSRobert Mustacchi 		val = i40e->i40e_rx_dma_min;
7079d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
7089d26e4fcSRobert Mustacchi 		val = i40e->i40e_tx_dma_min;
7099d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
7109d26e4fcSRobert Mustacchi 		val = i40e->i40e_rx_itr;
7119d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
7129d26e4fcSRobert Mustacchi 		val = i40e->i40e_tx_itr;
7139d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
7149d26e4fcSRobert Mustacchi 		val = i40e->i40e_other_itr;
7159d26e4fcSRobert Mustacchi 	} else {
7169d26e4fcSRobert Mustacchi 		return (ENOTSUP);
7179d26e4fcSRobert Mustacchi 	}
7189d26e4fcSRobert Mustacchi 
7199d26e4fcSRobert Mustacchi 	if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
7209d26e4fcSRobert Mustacchi 		return (ERANGE);
7219d26e4fcSRobert Mustacchi 	return (0);
7229d26e4fcSRobert Mustacchi }
7239d26e4fcSRobert Mustacchi 
7249d26e4fcSRobert Mustacchi /*
7259d26e4fcSRobert Mustacchi  * Annoyingly for private properties MAC seems to ignore default values that
7269d26e4fcSRobert Mustacchi  * aren't strings. That means that we have to translate all of these into
7279d26e4fcSRobert Mustacchi  * uint32_t's and instead we size the buffer to be large enough to hold a
7289d26e4fcSRobert Mustacchi  * uint32_t.
7299d26e4fcSRobert Mustacchi  */
7309d26e4fcSRobert Mustacchi /* ARGSUSED */
7319d26e4fcSRobert Mustacchi static void
7329d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name,
7339d26e4fcSRobert Mustacchi     mac_prop_info_handle_t prh)
7349d26e4fcSRobert Mustacchi {
7359d26e4fcSRobert Mustacchi 	char buf[64];
7369d26e4fcSRobert Mustacchi 	uint32_t def;
7379d26e4fcSRobert Mustacchi 
7389d26e4fcSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
7399d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
7409d26e4fcSRobert Mustacchi 		def = I40E_DEF_RX_DMA_THRESH;
7419d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh,
7429d26e4fcSRobert Mustacchi 		    I40E_MIN_RX_DMA_THRESH,
7439d26e4fcSRobert Mustacchi 		    I40E_MAX_RX_DMA_THRESH);
7449d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
7459d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
7469d26e4fcSRobert Mustacchi 		def = I40E_DEF_TX_DMA_THRESH;
7479d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh,
7489d26e4fcSRobert Mustacchi 		    I40E_MIN_TX_DMA_THRESH,
7499d26e4fcSRobert Mustacchi 		    I40E_MAX_TX_DMA_THRESH);
7509d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
7519d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
7529d26e4fcSRobert Mustacchi 		def = I40E_DEF_RX_ITR;
7539d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
7549d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
7559d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
7569d26e4fcSRobert Mustacchi 		def = I40E_DEF_TX_ITR;
7579d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
7589d26e4fcSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
7599d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
7609d26e4fcSRobert Mustacchi 		def = I40E_DEF_OTHER_ITR;
7619d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
7629d26e4fcSRobert Mustacchi 	} else {
7639d26e4fcSRobert Mustacchi 		return;
7649d26e4fcSRobert Mustacchi 	}
7659d26e4fcSRobert Mustacchi 
7669d26e4fcSRobert Mustacchi 	(void) snprintf(buf, sizeof (buf), "%d", def);
7679d26e4fcSRobert Mustacchi 	mac_prop_info_set_default_str(prh, buf);
7689d26e4fcSRobert Mustacchi }
7699d26e4fcSRobert Mustacchi 
7709d26e4fcSRobert Mustacchi static int
7719d26e4fcSRobert Mustacchi i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
7729d26e4fcSRobert Mustacchi     uint_t pr_valsize, const void *pr_val)
7739d26e4fcSRobert Mustacchi {
7749d26e4fcSRobert Mustacchi 	uint32_t new_mtu;
7759d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
7769d26e4fcSRobert Mustacchi 	int ret = 0;
7779d26e4fcSRobert Mustacchi 
7789d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
7799d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
7809d26e4fcSRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
7819d26e4fcSRobert Mustacchi 		return (ECANCELED);
7829d26e4fcSRobert Mustacchi 	}
7839d26e4fcSRobert Mustacchi 
7849d26e4fcSRobert Mustacchi 	switch (pr_num) {
7859d26e4fcSRobert Mustacchi 	/*
7869d26e4fcSRobert Mustacchi 	 * These properties are always read-only across every device.
7879d26e4fcSRobert Mustacchi 	 */
7889d26e4fcSRobert Mustacchi 	case MAC_PROP_DUPLEX:
7899d26e4fcSRobert Mustacchi 	case MAC_PROP_SPEED:
7909d26e4fcSRobert Mustacchi 	case MAC_PROP_STATUS:
7919d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
7929d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
7939d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
7943d75a287SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
7959d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
7969d26e4fcSRobert Mustacchi 		ret = ENOTSUP;
7979d26e4fcSRobert Mustacchi 		break;
7989d26e4fcSRobert Mustacchi 	/*
7999d26e4fcSRobert Mustacchi 	 * These are read-only at this time as we don't support configuring
8009d26e4fcSRobert Mustacchi 	 * auto-negotiation. See the theory statement in i40e_main.c.
8019d26e4fcSRobert Mustacchi 	 */
8029d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
8039d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
8049d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
8053d75a287SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
8069d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
8079d26e4fcSRobert Mustacchi 	case MAC_PROP_AUTONEG:
8089d26e4fcSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
8099d26e4fcSRobert Mustacchi 		ret = ENOTSUP;
8109d26e4fcSRobert Mustacchi 		break;
8119d26e4fcSRobert Mustacchi 
8129d26e4fcSRobert Mustacchi 	case MAC_PROP_MTU:
8139d26e4fcSRobert Mustacchi 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
8149d26e4fcSRobert Mustacchi 		if (new_mtu == i40e->i40e_sdu)
8159d26e4fcSRobert Mustacchi 			break;
8169d26e4fcSRobert Mustacchi 
8179d26e4fcSRobert Mustacchi 		if (new_mtu < I40E_MIN_MTU ||
8189d26e4fcSRobert Mustacchi 		    new_mtu > I40E_MAX_MTU) {
8199d26e4fcSRobert Mustacchi 			ret = EINVAL;
8209d26e4fcSRobert Mustacchi 			break;
8219d26e4fcSRobert Mustacchi 		}
8229d26e4fcSRobert Mustacchi 
8239d26e4fcSRobert Mustacchi 		if (i40e->i40e_state & I40E_STARTED) {
8249d26e4fcSRobert Mustacchi 			ret = EBUSY;
8259d26e4fcSRobert Mustacchi 			break;
8269d26e4fcSRobert Mustacchi 		}
8279d26e4fcSRobert Mustacchi 
8289d26e4fcSRobert Mustacchi 		ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu);
8299d26e4fcSRobert Mustacchi 		if (ret == 0) {
8309d26e4fcSRobert Mustacchi 			i40e->i40e_sdu = new_mtu;
8319d26e4fcSRobert Mustacchi 			i40e_update_mtu(i40e);
8329d26e4fcSRobert Mustacchi 		}
8339d26e4fcSRobert Mustacchi 		break;
8349d26e4fcSRobert Mustacchi 
8359d26e4fcSRobert Mustacchi 	case MAC_PROP_PRIVATE:
8369d26e4fcSRobert Mustacchi 		ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val);
8379d26e4fcSRobert Mustacchi 		break;
8389d26e4fcSRobert Mustacchi 	default:
8399d26e4fcSRobert Mustacchi 		ret = ENOTSUP;
8409d26e4fcSRobert Mustacchi 		break;
8419d26e4fcSRobert Mustacchi 	}
8429d26e4fcSRobert Mustacchi 
8439d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
8449d26e4fcSRobert Mustacchi 	return (ret);
8459d26e4fcSRobert Mustacchi }
8469d26e4fcSRobert Mustacchi 
8479d26e4fcSRobert Mustacchi static int
8489d26e4fcSRobert Mustacchi i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
8499d26e4fcSRobert Mustacchi     uint_t pr_valsize, void *pr_val)
8509d26e4fcSRobert Mustacchi {
8519d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
8529d26e4fcSRobert Mustacchi 	uint64_t speed;
8539d26e4fcSRobert Mustacchi 	int ret = 0;
8549d26e4fcSRobert Mustacchi 	uint8_t *u8;
8559d26e4fcSRobert Mustacchi 	link_flowctrl_t fctl;
8569d26e4fcSRobert Mustacchi 
8579d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
8589d26e4fcSRobert Mustacchi 
8599d26e4fcSRobert Mustacchi 	switch (pr_num) {
8609d26e4fcSRobert Mustacchi 	case MAC_PROP_DUPLEX:
8619d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (link_duplex_t)) {
8629d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
8639d26e4fcSRobert Mustacchi 			break;
8649d26e4fcSRobert Mustacchi 		}
8659d26e4fcSRobert Mustacchi 		bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t));
8669d26e4fcSRobert Mustacchi 		break;
8679d26e4fcSRobert Mustacchi 	case MAC_PROP_SPEED:
8689d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint64_t)) {
8699d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
8709d26e4fcSRobert Mustacchi 			break;
8719d26e4fcSRobert Mustacchi 		}
8729d26e4fcSRobert Mustacchi 		speed = i40e->i40e_link_speed * 1000000ULL;
8739d26e4fcSRobert Mustacchi 		bcopy(&speed, pr_val, sizeof (speed));
8749d26e4fcSRobert Mustacchi 		break;
8759d26e4fcSRobert Mustacchi 	case MAC_PROP_STATUS:
8769d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (link_state_t)) {
8779d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
8789d26e4fcSRobert Mustacchi 			break;
8799d26e4fcSRobert Mustacchi 		}
8809d26e4fcSRobert Mustacchi 		bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t));
8819d26e4fcSRobert Mustacchi 		break;
8829d26e4fcSRobert Mustacchi 	case MAC_PROP_AUTONEG:
8839d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
8849d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
8859d26e4fcSRobert Mustacchi 			break;
8869d26e4fcSRobert Mustacchi 		}
8879d26e4fcSRobert Mustacchi 		u8 = pr_val;
8889d26e4fcSRobert Mustacchi 		*u8 = 1;
8899d26e4fcSRobert Mustacchi 		break;
8909d26e4fcSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
8919d26e4fcSRobert Mustacchi 		/*
8929d26e4fcSRobert Mustacchi 		 * Because we don't currently support hardware flow control, we
8939d26e4fcSRobert Mustacchi 		 * just hardcode this to be none.
8949d26e4fcSRobert Mustacchi 		 */
8959d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (link_flowctrl_t)) {
8969d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
8979d26e4fcSRobert Mustacchi 			break;
8989d26e4fcSRobert Mustacchi 		}
8999d26e4fcSRobert Mustacchi 		fctl = LINK_FLOWCTRL_NONE;
9009d26e4fcSRobert Mustacchi 		bcopy(&fctl, pr_val, sizeof (link_flowctrl_t));
9019d26e4fcSRobert Mustacchi 		break;
9029d26e4fcSRobert Mustacchi 	case MAC_PROP_MTU:
9039d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint32_t)) {
9049d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
9059d26e4fcSRobert Mustacchi 			break;
9069d26e4fcSRobert Mustacchi 		}
9079d26e4fcSRobert Mustacchi 		bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t));
9089d26e4fcSRobert Mustacchi 		break;
9099d26e4fcSRobert Mustacchi 
9109d26e4fcSRobert Mustacchi 	/*
9119d26e4fcSRobert Mustacchi 	 * Because we don't let users control the speeds we may auto-negotiate
9129d26e4fcSRobert Mustacchi 	 * to, the values of the ADV_ and EN_ will always be the same.
9139d26e4fcSRobert Mustacchi 	 */
9149d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
9159d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
9169d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
9179d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
9189d26e4fcSRobert Mustacchi 			break;
9199d26e4fcSRobert Mustacchi 		}
9209d26e4fcSRobert Mustacchi 		u8 = pr_val;
9219d26e4fcSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0;
9229d26e4fcSRobert Mustacchi 		break;
9239d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
9249d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
9259d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
9269d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
9279d26e4fcSRobert Mustacchi 			break;
9289d26e4fcSRobert Mustacchi 		}
9299d26e4fcSRobert Mustacchi 		u8 = pr_val;
9309d26e4fcSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0;
9319d26e4fcSRobert Mustacchi 		break;
9329d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
9339d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
9349d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
9359d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
9369d26e4fcSRobert Mustacchi 			break;
9379d26e4fcSRobert Mustacchi 		}
9389d26e4fcSRobert Mustacchi 		u8 = pr_val;
9399d26e4fcSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0;
9409d26e4fcSRobert Mustacchi 		break;
9413d75a287SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
9423d75a287SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
9433d75a287SRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
9443d75a287SRobert Mustacchi 			ret = EOVERFLOW;
9453d75a287SRobert Mustacchi 			break;
9463d75a287SRobert Mustacchi 		}
9473d75a287SRobert Mustacchi 		u8 = pr_val;
9483d75a287SRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0;
9493d75a287SRobert Mustacchi 		break;
9509d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
9519d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
9529d26e4fcSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
9539d26e4fcSRobert Mustacchi 			ret = EOVERFLOW;
9549d26e4fcSRobert Mustacchi 			break;
9559d26e4fcSRobert Mustacchi 		}
9569d26e4fcSRobert Mustacchi 		u8 = pr_val;
9579d26e4fcSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0;
9589d26e4fcSRobert Mustacchi 		break;
9599d26e4fcSRobert Mustacchi 	case MAC_PROP_PRIVATE:
9609d26e4fcSRobert Mustacchi 		ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val);
9619d26e4fcSRobert Mustacchi 		break;
9629d26e4fcSRobert Mustacchi 	default:
9639d26e4fcSRobert Mustacchi 		ret = ENOTSUP;
9649d26e4fcSRobert Mustacchi 		break;
9659d26e4fcSRobert Mustacchi 	}
9669d26e4fcSRobert Mustacchi 
9679d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
9689d26e4fcSRobert Mustacchi 
9699d26e4fcSRobert Mustacchi 	return (ret);
9709d26e4fcSRobert Mustacchi }
9719d26e4fcSRobert Mustacchi 
9729d26e4fcSRobert Mustacchi static void
9739d26e4fcSRobert Mustacchi i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
9749d26e4fcSRobert Mustacchi     mac_prop_info_handle_t prh)
9759d26e4fcSRobert Mustacchi {
9769d26e4fcSRobert Mustacchi 	i40e_t *i40e = arg;
9779d26e4fcSRobert Mustacchi 
9789d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
9799d26e4fcSRobert Mustacchi 
9809d26e4fcSRobert Mustacchi 	switch (pr_num) {
9819d26e4fcSRobert Mustacchi 	case MAC_PROP_DUPLEX:
9829d26e4fcSRobert Mustacchi 	case MAC_PROP_SPEED:
9839d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
9849d26e4fcSRobert Mustacchi 		break;
9859d26e4fcSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
9869d26e4fcSRobert Mustacchi 		/*
9879d26e4fcSRobert Mustacchi 		 * At the moment, the driver doesn't support flow control, hence
9889d26e4fcSRobert Mustacchi 		 * why this is set to read-only and none.
9899d26e4fcSRobert Mustacchi 		 */
9909d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
9919d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_link_flowctrl(prh,
9929d26e4fcSRobert Mustacchi 		    LINK_FLOWCTRL_NONE);
9939d26e4fcSRobert Mustacchi 		break;
9949d26e4fcSRobert Mustacchi 	case MAC_PROP_MTU:
9959d26e4fcSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU);
9969d26e4fcSRobert Mustacchi 		break;
9979d26e4fcSRobert Mustacchi 
9989d26e4fcSRobert Mustacchi 	/*
9999d26e4fcSRobert Mustacchi 	 * We set the defaults for these based upon the phy's ability to
10009d26e4fcSRobert Mustacchi 	 * support the speeds. Note, auto-negotiation is required for fiber,
10019d26e4fcSRobert Mustacchi 	 * hence it is read-only and always enabled. When we have access to
10029d26e4fcSRobert Mustacchi 	 * copper phys we can revisit this.
10039d26e4fcSRobert Mustacchi 	 */
10049d26e4fcSRobert Mustacchi 	case MAC_PROP_AUTONEG:
10059d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10069d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh, 1);
10079d26e4fcSRobert Mustacchi 		break;
10089d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
10099d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10109d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10119d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
10129d26e4fcSRobert Mustacchi 		break;
10139d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
10149d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10159d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10169d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
10179d26e4fcSRobert Mustacchi 		break;
10189d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
10199d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10209d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10219d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
10229d26e4fcSRobert Mustacchi 		break;
10239d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
10249d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10259d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10269d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
10279d26e4fcSRobert Mustacchi 		break;
10289d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
10299d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10309d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10319d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
10329d26e4fcSRobert Mustacchi 		break;
10339d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
10349d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10359d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10369d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
10379d26e4fcSRobert Mustacchi 		break;
10383d75a287SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
10393d75a287SRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10403d75a287SRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10413d75a287SRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
10423d75a287SRobert Mustacchi 		break;
10433d75a287SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
10443d75a287SRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10453d75a287SRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10463d75a287SRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
10473d75a287SRobert Mustacchi 		break;
10489d26e4fcSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
10499d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10509d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10519d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
10529d26e4fcSRobert Mustacchi 		break;
10539d26e4fcSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
10549d26e4fcSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
10559d26e4fcSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
10569d26e4fcSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
10579d26e4fcSRobert Mustacchi 		break;
10589d26e4fcSRobert Mustacchi 	case MAC_PROP_PRIVATE:
10599d26e4fcSRobert Mustacchi 		i40e_m_propinfo_private(i40e, pr_name, prh);
10609d26e4fcSRobert Mustacchi 		break;
10619d26e4fcSRobert Mustacchi 	default:
10629d26e4fcSRobert Mustacchi 		break;
10639d26e4fcSRobert Mustacchi 	}
10649d26e4fcSRobert Mustacchi 
10659d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
10669d26e4fcSRobert Mustacchi }
10679d26e4fcSRobert Mustacchi 
10689d26e4fcSRobert Mustacchi #define	I40E_M_CALLBACK_FLAGS \
10699d26e4fcSRobert Mustacchi 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
10709d26e4fcSRobert Mustacchi 
10719d26e4fcSRobert Mustacchi static mac_callbacks_t i40e_m_callbacks = {
10729d26e4fcSRobert Mustacchi 	I40E_M_CALLBACK_FLAGS,
10739d26e4fcSRobert Mustacchi 	i40e_m_stat,
10749d26e4fcSRobert Mustacchi 	i40e_m_start,
10759d26e4fcSRobert Mustacchi 	i40e_m_stop,
10769d26e4fcSRobert Mustacchi 	i40e_m_promisc,
10779d26e4fcSRobert Mustacchi 	i40e_m_multicast,
10789d26e4fcSRobert Mustacchi 	NULL,
10799d26e4fcSRobert Mustacchi 	NULL,
10809d26e4fcSRobert Mustacchi 	NULL,
10819d26e4fcSRobert Mustacchi 	i40e_m_ioctl,
10829d26e4fcSRobert Mustacchi 	i40e_m_getcapab,
10839d26e4fcSRobert Mustacchi 	NULL,
10849d26e4fcSRobert Mustacchi 	NULL,
10859d26e4fcSRobert Mustacchi 	i40e_m_setprop,
10869d26e4fcSRobert Mustacchi 	i40e_m_getprop,
10879d26e4fcSRobert Mustacchi 	i40e_m_propinfo
10889d26e4fcSRobert Mustacchi };
10899d26e4fcSRobert Mustacchi 
10909d26e4fcSRobert Mustacchi boolean_t
10919d26e4fcSRobert Mustacchi i40e_register_mac(i40e_t *i40e)
10929d26e4fcSRobert Mustacchi {
10939d26e4fcSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
10949d26e4fcSRobert Mustacchi 	int status;
10959d26e4fcSRobert Mustacchi 	mac_register_t *mac = mac_alloc(MAC_VERSION);
10969d26e4fcSRobert Mustacchi 
10979d26e4fcSRobert Mustacchi 	if (mac == NULL)
10989d26e4fcSRobert Mustacchi 		return (B_FALSE);
10999d26e4fcSRobert Mustacchi 
11009d26e4fcSRobert Mustacchi 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
11019d26e4fcSRobert Mustacchi 	mac->m_driver = i40e;
11029d26e4fcSRobert Mustacchi 	mac->m_dip = i40e->i40e_dip;
11039d26e4fcSRobert Mustacchi 	mac->m_src_addr = hw->mac.addr;
11049d26e4fcSRobert Mustacchi 	mac->m_callbacks = &i40e_m_callbacks;
11059d26e4fcSRobert Mustacchi 	mac->m_min_sdu = 0;
11069d26e4fcSRobert Mustacchi 	mac->m_max_sdu = i40e->i40e_sdu;
11079d26e4fcSRobert Mustacchi 	mac->m_margin = VLAN_TAGSZ;
11089d26e4fcSRobert Mustacchi 	mac->m_priv_props = i40e_priv_props;
11099d26e4fcSRobert Mustacchi 	mac->m_v12n = MAC_VIRT_LEVEL1;
11109d26e4fcSRobert Mustacchi 
11119d26e4fcSRobert Mustacchi 	status = mac_register(mac, &i40e->i40e_mac_hdl);
11129d26e4fcSRobert Mustacchi 	if (status != 0)
11139d26e4fcSRobert Mustacchi 		i40e_error(i40e, "mac_register() returned %d", status);
11149d26e4fcSRobert Mustacchi 	mac_free(mac);
11159d26e4fcSRobert Mustacchi 
11169d26e4fcSRobert Mustacchi 	return (status == 0);
11179d26e4fcSRobert Mustacchi }
1118