xref: /titanic_44/usr/src/uts/common/io/i40e/i40e_gld.c (revision 5ca90d72bb15ab4b88b7497504cdd4408d82faab)
1f2f3bb8fSRobert Mustacchi /*
2f2f3bb8fSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3f2f3bb8fSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4f2f3bb8fSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5f2f3bb8fSRobert Mustacchi  * 1.0 of the CDDL.
6f2f3bb8fSRobert Mustacchi  *
7f2f3bb8fSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8f2f3bb8fSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9f2f3bb8fSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10f2f3bb8fSRobert Mustacchi  */
11f2f3bb8fSRobert Mustacchi 
12f2f3bb8fSRobert Mustacchi /*
13f2f3bb8fSRobert Mustacchi  * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
147e6ab961SRobert Mustacchi  * Copyright (c) 2018, Joyent, Inc.
1547fdb1a2SPaul Winder  * Copyright 2017 Tegile Systems, Inc.  All rights reserved.
16f2f3bb8fSRobert Mustacchi  */
17f2f3bb8fSRobert Mustacchi 
18f2f3bb8fSRobert Mustacchi /*
19f2f3bb8fSRobert Mustacchi  * For more information, please see the big theory statement in i40e_main.c.
20f2f3bb8fSRobert Mustacchi  */
21f2f3bb8fSRobert Mustacchi 
22f2f3bb8fSRobert Mustacchi #include "i40e_sw.h"
23f2f3bb8fSRobert Mustacchi 
24f2f3bb8fSRobert Mustacchi #define	I40E_PROP_RX_DMA_THRESH	"_rx_dma_threshold"
25f2f3bb8fSRobert Mustacchi #define	I40E_PROP_TX_DMA_THRESH	"_tx_dma_threshold"
26f2f3bb8fSRobert Mustacchi #define	I40E_PROP_RX_ITR	"_rx_intr_throttle"
27f2f3bb8fSRobert Mustacchi #define	I40E_PROP_TX_ITR	"_tx_intr_throttle"
28f2f3bb8fSRobert Mustacchi #define	I40E_PROP_OTHER_ITR	"_other_intr_throttle"
29f2f3bb8fSRobert Mustacchi 
30f2f3bb8fSRobert Mustacchi char *i40e_priv_props[] = {
31f2f3bb8fSRobert Mustacchi 	I40E_PROP_RX_DMA_THRESH,
32f2f3bb8fSRobert Mustacchi 	I40E_PROP_TX_DMA_THRESH,
33f2f3bb8fSRobert Mustacchi 	I40E_PROP_RX_ITR,
34f2f3bb8fSRobert Mustacchi 	I40E_PROP_TX_ITR,
35f2f3bb8fSRobert Mustacchi 	I40E_PROP_OTHER_ITR,
36f2f3bb8fSRobert Mustacchi 	NULL
37f2f3bb8fSRobert Mustacchi };
38f2f3bb8fSRobert Mustacchi 
39f2f3bb8fSRobert Mustacchi static int
i40e_group_remove_mac(void * arg,const uint8_t * mac_addr)40f2f3bb8fSRobert Mustacchi i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
41f2f3bb8fSRobert Mustacchi {
42*5ca90d72SRyan Zezeski 	i40e_rx_group_t *rxg = arg;
43*5ca90d72SRyan Zezeski 	i40e_t *i40e = rxg->irg_i40e;
44f2f3bb8fSRobert Mustacchi 	struct i40e_aqc_remove_macvlan_element_data filt;
45f2f3bb8fSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
46f2f3bb8fSRobert Mustacchi 	int ret, i, last;
47f2f3bb8fSRobert Mustacchi 	i40e_uaddr_t *iua;
48f2f3bb8fSRobert Mustacchi 
49f2f3bb8fSRobert Mustacchi 	if (I40E_IS_MULTICAST(mac_addr))
50f2f3bb8fSRobert Mustacchi 		return (EINVAL);
51f2f3bb8fSRobert Mustacchi 
52f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
53f2f3bb8fSRobert Mustacchi 
54f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
55f2f3bb8fSRobert Mustacchi 		ret = ECANCELED;
56f2f3bb8fSRobert Mustacchi 		goto done;
57f2f3bb8fSRobert Mustacchi 	}
58f2f3bb8fSRobert Mustacchi 
59f2f3bb8fSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
60f2f3bb8fSRobert Mustacchi 		if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
61f2f3bb8fSRobert Mustacchi 		    ETHERADDRL) == 0)
62f2f3bb8fSRobert Mustacchi 			break;
63f2f3bb8fSRobert Mustacchi 	}
64f2f3bb8fSRobert Mustacchi 
65f2f3bb8fSRobert Mustacchi 	if (i == i40e->i40e_resources.ifr_nmacfilt_used) {
66f2f3bb8fSRobert Mustacchi 		ret = ENOENT;
67f2f3bb8fSRobert Mustacchi 		goto done;
68f2f3bb8fSRobert Mustacchi 	}
69f2f3bb8fSRobert Mustacchi 
70f2f3bb8fSRobert Mustacchi 	iua = &i40e->i40e_uaddrs[i];
71f2f3bb8fSRobert Mustacchi 	ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0);
72f2f3bb8fSRobert Mustacchi 
73f2f3bb8fSRobert Mustacchi 	bzero(&filt, sizeof (filt));
74f2f3bb8fSRobert Mustacchi 	bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
75f2f3bb8fSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
76f2f3bb8fSRobert Mustacchi 	    I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
77f2f3bb8fSRobert Mustacchi 
78f2f3bb8fSRobert Mustacchi 	if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) !=
79f2f3bb8fSRobert Mustacchi 	    I40E_SUCCESS) {
80f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "failed to remove mac address "
81f2f3bb8fSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
82f2f3bb8fSRobert Mustacchi 		    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
83f2f3bb8fSRobert Mustacchi 		    mac_addr[4], mac_addr[5], filt.error_code);
84f2f3bb8fSRobert Mustacchi 		ret = EIO;
85f2f3bb8fSRobert Mustacchi 		goto done;
86f2f3bb8fSRobert Mustacchi 	}
87f2f3bb8fSRobert Mustacchi 
88f2f3bb8fSRobert Mustacchi 	last = i40e->i40e_resources.ifr_nmacfilt_used - 1;
89f2f3bb8fSRobert Mustacchi 	if (i != last) {
90f2f3bb8fSRobert Mustacchi 		i40e_uaddr_t *src = &i40e->i40e_uaddrs[last];
91f2f3bb8fSRobert Mustacchi 		bcopy(src, iua, sizeof (i40e_uaddr_t));
92f2f3bb8fSRobert Mustacchi 	}
93f2f3bb8fSRobert Mustacchi 
94f2f3bb8fSRobert Mustacchi 	/*
95f2f3bb8fSRobert Mustacchi 	 * Set the multicast bit in the last one to indicate to ourselves that
96f2f3bb8fSRobert Mustacchi 	 * it's invalid.
97f2f3bb8fSRobert Mustacchi 	 */
98f2f3bb8fSRobert Mustacchi 	bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t));
99f2f3bb8fSRobert Mustacchi 	i40e->i40e_uaddrs[last].iua_mac[0] = 0x01;
100f2f3bb8fSRobert Mustacchi 	i40e->i40e_resources.ifr_nmacfilt_used--;
101f2f3bb8fSRobert Mustacchi 	ret = 0;
102f2f3bb8fSRobert Mustacchi done:
103f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
104f2f3bb8fSRobert Mustacchi 
105f2f3bb8fSRobert Mustacchi 	return (ret);
106f2f3bb8fSRobert Mustacchi }
107f2f3bb8fSRobert Mustacchi 
108f2f3bb8fSRobert Mustacchi static int
i40e_group_add_mac(void * arg,const uint8_t * mac_addr)109f2f3bb8fSRobert Mustacchi i40e_group_add_mac(void *arg, const uint8_t *mac_addr)
110f2f3bb8fSRobert Mustacchi {
111*5ca90d72SRyan Zezeski 	i40e_rx_group_t	*rxg = arg;
112*5ca90d72SRyan Zezeski 	i40e_t		*i40e = rxg->irg_i40e;
113f2f3bb8fSRobert Mustacchi 	struct i40e_hw	*hw = &i40e->i40e_hw_space;
114f2f3bb8fSRobert Mustacchi 	int		i, ret;
115f2f3bb8fSRobert Mustacchi 	i40e_uaddr_t	*iua;
116f2f3bb8fSRobert Mustacchi 	struct i40e_aqc_add_macvlan_element_data filt;
117f2f3bb8fSRobert Mustacchi 
118f2f3bb8fSRobert Mustacchi 	if (I40E_IS_MULTICAST(mac_addr))
119f2f3bb8fSRobert Mustacchi 		return (EINVAL);
120f2f3bb8fSRobert Mustacchi 
121f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
122f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
123f2f3bb8fSRobert Mustacchi 		ret = ECANCELED;
124f2f3bb8fSRobert Mustacchi 		goto done;
125f2f3bb8fSRobert Mustacchi 	}
126f2f3bb8fSRobert Mustacchi 
127f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_resources.ifr_nmacfilt ==
128f2f3bb8fSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmacfilt_used) {
129f2f3bb8fSRobert Mustacchi 		ret = ENOSPC;
130f2f3bb8fSRobert Mustacchi 		goto done;
131f2f3bb8fSRobert Mustacchi 	}
132f2f3bb8fSRobert Mustacchi 
133f2f3bb8fSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
134f2f3bb8fSRobert Mustacchi 		if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
135f2f3bb8fSRobert Mustacchi 		    ETHERADDRL) == 0) {
136f2f3bb8fSRobert Mustacchi 			ret = EEXIST;
137f2f3bb8fSRobert Mustacchi 			goto done;
138f2f3bb8fSRobert Mustacchi 		}
139f2f3bb8fSRobert Mustacchi 	}
140f2f3bb8fSRobert Mustacchi 
141f2f3bb8fSRobert Mustacchi 	bzero(&filt, sizeof (filt));
142f2f3bb8fSRobert Mustacchi 	bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
143f2f3bb8fSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH	|
144f2f3bb8fSRobert Mustacchi 	    I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
145f2f3bb8fSRobert Mustacchi 
146*5ca90d72SRyan Zezeski 	if ((ret = i40e_aq_add_macvlan(hw, rxg->irg_vsi_seid, &filt, 1,
147f2f3bb8fSRobert Mustacchi 	    NULL)) != I40E_SUCCESS) {
148f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "failed to add mac address "
149f2f3bb8fSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
150f2f3bb8fSRobert Mustacchi 		    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
151f2f3bb8fSRobert Mustacchi 		    mac_addr[4], mac_addr[5], ret);
152f2f3bb8fSRobert Mustacchi 		ret = EIO;
153f2f3bb8fSRobert Mustacchi 		goto done;
154f2f3bb8fSRobert Mustacchi 	}
155f2f3bb8fSRobert Mustacchi 
156f2f3bb8fSRobert Mustacchi 	iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used];
157f2f3bb8fSRobert Mustacchi 	bcopy(mac_addr, iua->iua_mac, ETHERADDRL);
158*5ca90d72SRyan Zezeski 	iua->iua_vsi = rxg->irg_vsi_seid;
159f2f3bb8fSRobert Mustacchi 	i40e->i40e_resources.ifr_nmacfilt_used++;
160f2f3bb8fSRobert Mustacchi 	ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <=
161f2f3bb8fSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmacfilt);
162f2f3bb8fSRobert Mustacchi 	ret = 0;
163f2f3bb8fSRobert Mustacchi done:
164f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
165f2f3bb8fSRobert Mustacchi 	return (ret);
166f2f3bb8fSRobert Mustacchi }
167f2f3bb8fSRobert Mustacchi 
168f2f3bb8fSRobert Mustacchi static int
i40e_m_start(void * arg)169f2f3bb8fSRobert Mustacchi i40e_m_start(void *arg)
170f2f3bb8fSRobert Mustacchi {
171f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
172f2f3bb8fSRobert Mustacchi 	int rc = 0;
173f2f3bb8fSRobert Mustacchi 
174f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
175f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
176f2f3bb8fSRobert Mustacchi 		rc = ECANCELED;
177f2f3bb8fSRobert Mustacchi 		goto done;
178f2f3bb8fSRobert Mustacchi 	}
179f2f3bb8fSRobert Mustacchi 
180f2f3bb8fSRobert Mustacchi 	if (!i40e_start(i40e, B_TRUE)) {
181f2f3bb8fSRobert Mustacchi 		rc = EIO;
182f2f3bb8fSRobert Mustacchi 		goto done;
183f2f3bb8fSRobert Mustacchi 	}
184f2f3bb8fSRobert Mustacchi 
185f2f3bb8fSRobert Mustacchi 	atomic_or_32(&i40e->i40e_state, I40E_STARTED);
186f2f3bb8fSRobert Mustacchi done:
187f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
188f2f3bb8fSRobert Mustacchi 
189f2f3bb8fSRobert Mustacchi 	return (rc);
190f2f3bb8fSRobert Mustacchi }
191f2f3bb8fSRobert Mustacchi 
192f2f3bb8fSRobert Mustacchi static void
i40e_m_stop(void * arg)193f2f3bb8fSRobert Mustacchi i40e_m_stop(void *arg)
194f2f3bb8fSRobert Mustacchi {
195f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
196f2f3bb8fSRobert Mustacchi 
197f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
198f2f3bb8fSRobert Mustacchi 
199f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED)
200f2f3bb8fSRobert Mustacchi 		goto done;
201f2f3bb8fSRobert Mustacchi 
202f2f3bb8fSRobert Mustacchi 	atomic_and_32(&i40e->i40e_state, ~I40E_STARTED);
203f2f3bb8fSRobert Mustacchi 	i40e_stop(i40e, B_TRUE);
204f2f3bb8fSRobert Mustacchi done:
205f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
206f2f3bb8fSRobert Mustacchi }
207f2f3bb8fSRobert Mustacchi 
208f2f3bb8fSRobert Mustacchi /*
209f2f3bb8fSRobert Mustacchi  * Enable and disable promiscuous mode as requested. We have to toggle both
210f2f3bb8fSRobert Mustacchi  * unicast and multicast. Note that multicast may already be enabled due to the
211f2f3bb8fSRobert Mustacchi  * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
212f2f3bb8fSRobert Mustacchi  * on this.
213f2f3bb8fSRobert Mustacchi  */
214f2f3bb8fSRobert Mustacchi static int
i40e_m_promisc(void * arg,boolean_t on)215f2f3bb8fSRobert Mustacchi i40e_m_promisc(void *arg, boolean_t on)
216f2f3bb8fSRobert Mustacchi {
217f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
218f2f3bb8fSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
219f2f3bb8fSRobert Mustacchi 	int ret = 0, err = 0;
220f2f3bb8fSRobert Mustacchi 
221f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
222f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
223f2f3bb8fSRobert Mustacchi 		ret = ECANCELED;
224f2f3bb8fSRobert Mustacchi 		goto done;
225f2f3bb8fSRobert Mustacchi 	}
226f2f3bb8fSRobert Mustacchi 
227f2f3bb8fSRobert Mustacchi 
228*5ca90d72SRyan Zezeski 	ret = i40e_aq_set_vsi_unicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
2298f179fb3SRobert Mustacchi 	    on, NULL, B_FALSE);
230f2f3bb8fSRobert Mustacchi 	if (ret != I40E_SUCCESS) {
231f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "failed to %s unicast promiscuity on "
232f2f3bb8fSRobert Mustacchi 		    "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
233f2f3bb8fSRobert Mustacchi 		    ret);
234f2f3bb8fSRobert Mustacchi 		err = EIO;
235f2f3bb8fSRobert Mustacchi 		goto done;
236f2f3bb8fSRobert Mustacchi 	}
237f2f3bb8fSRobert Mustacchi 
238f2f3bb8fSRobert Mustacchi 	/*
239f2f3bb8fSRobert Mustacchi 	 * If we have a non-zero mcast_promisc_count, then it has already been
240f2f3bb8fSRobert Mustacchi 	 * enabled or we need to leave it that way and not touch it.
241f2f3bb8fSRobert Mustacchi 	 */
242f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_mcast_promisc_count > 0) {
243f2f3bb8fSRobert Mustacchi 		i40e->i40e_promisc_on = on;
244f2f3bb8fSRobert Mustacchi 		goto done;
245f2f3bb8fSRobert Mustacchi 	}
246f2f3bb8fSRobert Mustacchi 
247*5ca90d72SRyan Zezeski 	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
248f2f3bb8fSRobert Mustacchi 	    on, NULL);
249f2f3bb8fSRobert Mustacchi 	if (ret != I40E_SUCCESS) {
250f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "failed to %s multicast promiscuity on "
251f2f3bb8fSRobert Mustacchi 		    "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
252f2f3bb8fSRobert Mustacchi 		    ret);
253f2f3bb8fSRobert Mustacchi 
254f2f3bb8fSRobert Mustacchi 		/*
255f2f3bb8fSRobert Mustacchi 		 * Try our best to put us back into a state that MAC expects us
256f2f3bb8fSRobert Mustacchi 		 * to be in.
257f2f3bb8fSRobert Mustacchi 		 */
258*5ca90d72SRyan Zezeski 		ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
259*5ca90d72SRyan Zezeski 		    I40E_DEF_VSI_SEID(i40e), !on, NULL, B_FALSE);
260f2f3bb8fSRobert Mustacchi 		if (ret != I40E_SUCCESS) {
261f2f3bb8fSRobert Mustacchi 			i40e_error(i40e, "failed to %s unicast promiscuity on "
262f2f3bb8fSRobert Mustacchi 			    "the default VSI after toggling multicast failed: "
263f2f3bb8fSRobert Mustacchi 			    "%d", on == B_TRUE ? "disable" : "enable", ret);
264f2f3bb8fSRobert Mustacchi 		}
265f2f3bb8fSRobert Mustacchi 
266f2f3bb8fSRobert Mustacchi 		err = EIO;
267f2f3bb8fSRobert Mustacchi 		goto done;
268f2f3bb8fSRobert Mustacchi 	} else {
269f2f3bb8fSRobert Mustacchi 		i40e->i40e_promisc_on = on;
270f2f3bb8fSRobert Mustacchi 	}
271f2f3bb8fSRobert Mustacchi 
272f2f3bb8fSRobert Mustacchi done:
273f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
274f2f3bb8fSRobert Mustacchi 	return (err);
275f2f3bb8fSRobert Mustacchi }
276f2f3bb8fSRobert Mustacchi 
277f2f3bb8fSRobert Mustacchi /*
278f2f3bb8fSRobert Mustacchi  * See the big theory statement in i40e_main.c for multicast address management.
279f2f3bb8fSRobert Mustacchi  */
280f2f3bb8fSRobert Mustacchi static int
i40e_multicast_add(i40e_t * i40e,const uint8_t * multicast_address)281f2f3bb8fSRobert Mustacchi i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address)
282f2f3bb8fSRobert Mustacchi {
283f2f3bb8fSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
284f2f3bb8fSRobert Mustacchi 	struct i40e_aqc_add_macvlan_element_data filt;
285f2f3bb8fSRobert Mustacchi 	i40e_maddr_t *mc;
286f2f3bb8fSRobert Mustacchi 	int ret;
287f2f3bb8fSRobert Mustacchi 
288f2f3bb8fSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
289f2f3bb8fSRobert Mustacchi 
290f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_resources.ifr_nmcastfilt_used ==
291f2f3bb8fSRobert Mustacchi 	    i40e->i40e_resources.ifr_nmcastfilt) {
292f2f3bb8fSRobert Mustacchi 		if (i40e->i40e_mcast_promisc_count == 0 &&
293f2f3bb8fSRobert Mustacchi 		    i40e->i40e_promisc_on == B_FALSE) {
294f2f3bb8fSRobert Mustacchi 			ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
295*5ca90d72SRyan Zezeski 			    I40E_DEF_VSI_SEID(i40e), B_TRUE, NULL);
296f2f3bb8fSRobert Mustacchi 			if (ret != I40E_SUCCESS) {
297f2f3bb8fSRobert Mustacchi 				i40e_error(i40e, "failed to enable multicast "
298f2f3bb8fSRobert Mustacchi 				    "promiscuous mode on VSI %d: %d",
299*5ca90d72SRyan Zezeski 				    I40E_DEF_VSI_SEID(i40e), ret);
300f2f3bb8fSRobert Mustacchi 				return (EIO);
301f2f3bb8fSRobert Mustacchi 			}
302f2f3bb8fSRobert Mustacchi 		}
303f2f3bb8fSRobert Mustacchi 		i40e->i40e_mcast_promisc_count++;
304f2f3bb8fSRobert Mustacchi 		return (0);
305f2f3bb8fSRobert Mustacchi 	}
306f2f3bb8fSRobert Mustacchi 
307f2f3bb8fSRobert Mustacchi 	mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used];
308f2f3bb8fSRobert Mustacchi 	bzero(&filt, sizeof (filt));
309f2f3bb8fSRobert Mustacchi 	bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
310f2f3bb8fSRobert Mustacchi 	filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |
311f2f3bb8fSRobert Mustacchi 	    I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
312f2f3bb8fSRobert Mustacchi 
313*5ca90d72SRyan Zezeski 	if ((ret = i40e_aq_add_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt, 1,
314f2f3bb8fSRobert Mustacchi 	    NULL)) != I40E_SUCCESS) {
315f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "failed to add mac address "
316f2f3bb8fSRobert Mustacchi 		    "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
317f2f3bb8fSRobert Mustacchi 		    multicast_address[0], multicast_address[1],
318f2f3bb8fSRobert Mustacchi 		    multicast_address[2], multicast_address[3],
319f2f3bb8fSRobert Mustacchi 		    multicast_address[4], multicast_address[5],
320f2f3bb8fSRobert Mustacchi 		    ret);
321f2f3bb8fSRobert Mustacchi 		return (EIO);
322f2f3bb8fSRobert Mustacchi 	}
323f2f3bb8fSRobert Mustacchi 
324f2f3bb8fSRobert Mustacchi 	bcopy(multicast_address, mc->ima_mac, ETHERADDRL);
325f2f3bb8fSRobert Mustacchi 	i40e->i40e_resources.ifr_nmcastfilt_used++;
326f2f3bb8fSRobert Mustacchi 	return (0);
327f2f3bb8fSRobert Mustacchi }
328f2f3bb8fSRobert Mustacchi 
329f2f3bb8fSRobert Mustacchi /*
330f2f3bb8fSRobert Mustacchi  * See the big theory statement in i40e_main.c for multicast address management.
331f2f3bb8fSRobert Mustacchi  */
332f2f3bb8fSRobert Mustacchi static int
i40e_multicast_remove(i40e_t * i40e,const uint8_t * multicast_address)333f2f3bb8fSRobert Mustacchi i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address)
334f2f3bb8fSRobert Mustacchi {
335f2f3bb8fSRobert Mustacchi 	int i, ret;
336f2f3bb8fSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
337f2f3bb8fSRobert Mustacchi 
338f2f3bb8fSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
339f2f3bb8fSRobert Mustacchi 
340f2f3bb8fSRobert Mustacchi 	for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) {
341f2f3bb8fSRobert Mustacchi 		struct i40e_aqc_remove_macvlan_element_data filt;
342f2f3bb8fSRobert Mustacchi 		int last;
343f2f3bb8fSRobert Mustacchi 
344f2f3bb8fSRobert Mustacchi 		if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac,
345f2f3bb8fSRobert Mustacchi 		    ETHERADDRL) != 0) {
346f2f3bb8fSRobert Mustacchi 			continue;
347f2f3bb8fSRobert Mustacchi 		}
348f2f3bb8fSRobert Mustacchi 
349f2f3bb8fSRobert Mustacchi 		bzero(&filt, sizeof (filt));
350f2f3bb8fSRobert Mustacchi 		bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
351f2f3bb8fSRobert Mustacchi 		filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |
352f2f3bb8fSRobert Mustacchi 		    I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
353f2f3bb8fSRobert Mustacchi 
354*5ca90d72SRyan Zezeski 		if (i40e_aq_remove_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt,
355*5ca90d72SRyan Zezeski 		    1, NULL) != I40E_SUCCESS) {
356f2f3bb8fSRobert Mustacchi 			i40e_error(i40e, "failed to remove mac address "
357f2f3bb8fSRobert Mustacchi 			    "%2x:%2x:%2x:%2x:%2x:%2x from multicast "
358f2f3bb8fSRobert Mustacchi 			    "filter: %d",
359f2f3bb8fSRobert Mustacchi 			    multicast_address[0], multicast_address[1],
360f2f3bb8fSRobert Mustacchi 			    multicast_address[2], multicast_address[3],
361f2f3bb8fSRobert Mustacchi 			    multicast_address[4], multicast_address[5],
362f2f3bb8fSRobert Mustacchi 			    filt.error_code);
363f2f3bb8fSRobert Mustacchi 			return (EIO);
364f2f3bb8fSRobert Mustacchi 		}
365f2f3bb8fSRobert Mustacchi 
366f2f3bb8fSRobert Mustacchi 		last = i40e->i40e_resources.ifr_nmcastfilt_used - 1;
367f2f3bb8fSRobert Mustacchi 		if (i != last) {
368f2f3bb8fSRobert Mustacchi 			bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i],
369f2f3bb8fSRobert Mustacchi 			    sizeof (i40e_maddr_t));
370f2f3bb8fSRobert Mustacchi 			bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t));
371f2f3bb8fSRobert Mustacchi 		}
372f2f3bb8fSRobert Mustacchi 
373f2f3bb8fSRobert Mustacchi 		ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0);
374f2f3bb8fSRobert Mustacchi 		i40e->i40e_resources.ifr_nmcastfilt_used--;
375f2f3bb8fSRobert Mustacchi 		return (0);
376f2f3bb8fSRobert Mustacchi 	}
377f2f3bb8fSRobert Mustacchi 
378f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_mcast_promisc_count > 0) {
379f2f3bb8fSRobert Mustacchi 		if (i40e->i40e_mcast_promisc_count == 1 &&
380f2f3bb8fSRobert Mustacchi 		    i40e->i40e_promisc_on == B_FALSE) {
381f2f3bb8fSRobert Mustacchi 			ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
382*5ca90d72SRyan Zezeski 			    I40E_DEF_VSI_SEID(i40e), B_FALSE, NULL);
383f2f3bb8fSRobert Mustacchi 			if (ret != I40E_SUCCESS) {
384f2f3bb8fSRobert Mustacchi 				i40e_error(i40e, "failed to disable "
385f2f3bb8fSRobert Mustacchi 				    "multicast promiscuous mode on VSI %d: %d",
386*5ca90d72SRyan Zezeski 				    I40E_DEF_VSI_SEID(i40e), ret);
387f2f3bb8fSRobert Mustacchi 				return (EIO);
388f2f3bb8fSRobert Mustacchi 			}
389f2f3bb8fSRobert Mustacchi 		}
390f2f3bb8fSRobert Mustacchi 		i40e->i40e_mcast_promisc_count--;
391f2f3bb8fSRobert Mustacchi 
392f2f3bb8fSRobert Mustacchi 		return (0);
393f2f3bb8fSRobert Mustacchi 	}
394f2f3bb8fSRobert Mustacchi 
395f2f3bb8fSRobert Mustacchi 	return (ENOENT);
396f2f3bb8fSRobert Mustacchi }
397f2f3bb8fSRobert Mustacchi 
398f2f3bb8fSRobert Mustacchi static int
i40e_m_multicast(void * arg,boolean_t add,const uint8_t * multicast_address)399f2f3bb8fSRobert Mustacchi i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
400f2f3bb8fSRobert Mustacchi {
401f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
402f2f3bb8fSRobert Mustacchi 	int rc;
403f2f3bb8fSRobert Mustacchi 
404f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
405f2f3bb8fSRobert Mustacchi 
406f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
407f2f3bb8fSRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
408f2f3bb8fSRobert Mustacchi 		return (ECANCELED);
409f2f3bb8fSRobert Mustacchi 	}
410f2f3bb8fSRobert Mustacchi 
411f2f3bb8fSRobert Mustacchi 	if (add == B_TRUE) {
412f2f3bb8fSRobert Mustacchi 		rc = i40e_multicast_add(i40e, multicast_address);
413f2f3bb8fSRobert Mustacchi 	} else {
414f2f3bb8fSRobert Mustacchi 		rc = i40e_multicast_remove(i40e, multicast_address);
415f2f3bb8fSRobert Mustacchi 	}
416f2f3bb8fSRobert Mustacchi 
417f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
418f2f3bb8fSRobert Mustacchi 	return (rc);
419f2f3bb8fSRobert Mustacchi }
420f2f3bb8fSRobert Mustacchi 
421f2f3bb8fSRobert Mustacchi /* ARGSUSED */
422f2f3bb8fSRobert Mustacchi static void
i40e_m_ioctl(void * arg,queue_t * q,mblk_t * mp)423f2f3bb8fSRobert Mustacchi i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
424f2f3bb8fSRobert Mustacchi {
425f2f3bb8fSRobert Mustacchi 	/*
426f2f3bb8fSRobert Mustacchi 	 * At this time, we don't support toggling i40e into loopback mode. It's
427f2f3bb8fSRobert Mustacchi 	 * questionable how much value this has when there's no clear way to
428f2f3bb8fSRobert Mustacchi 	 * toggle this behavior from a supported way in userland.
429f2f3bb8fSRobert Mustacchi 	 */
430f2f3bb8fSRobert Mustacchi 	miocnak(q, mp, 0, EINVAL);
431f2f3bb8fSRobert Mustacchi }
432f2f3bb8fSRobert Mustacchi 
433f2f3bb8fSRobert Mustacchi static int
i40e_ring_start(mac_ring_driver_t rh,uint64_t gen_num)434f2f3bb8fSRobert Mustacchi i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num)
435f2f3bb8fSRobert Mustacchi {
436f2f3bb8fSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
437f2f3bb8fSRobert Mustacchi 
438f2f3bb8fSRobert Mustacchi 	/*
439f2f3bb8fSRobert Mustacchi 	 * GLDv3 requires we keep track of a generation number, as it uses
440f2f3bb8fSRobert Mustacchi 	 * that number to keep track of whether or not a ring is active.
441f2f3bb8fSRobert Mustacchi 	 */
442f2f3bb8fSRobert Mustacchi 	mutex_enter(&itrq->itrq_rx_lock);
443f2f3bb8fSRobert Mustacchi 	itrq->itrq_rxgen = gen_num;
444f2f3bb8fSRobert Mustacchi 	mutex_exit(&itrq->itrq_rx_lock);
445f2f3bb8fSRobert Mustacchi 	return (0);
446f2f3bb8fSRobert Mustacchi }
447f2f3bb8fSRobert Mustacchi 
448f2f3bb8fSRobert Mustacchi /* ARGSUSED */
449f2f3bb8fSRobert Mustacchi static int
i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)450f2f3bb8fSRobert Mustacchi i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)
451f2f3bb8fSRobert Mustacchi {
452f2f3bb8fSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
453f2f3bb8fSRobert Mustacchi 
45447fdb1a2SPaul Winder 	mutex_enter(&itrq->itrq_rx_lock);
45547fdb1a2SPaul Winder 	ASSERT(itrq->itrq_intr_poll == B_TRUE);
4565b7cbeceSRobert Mustacchi 	i40e_intr_rx_queue_enable(itrq);
45747fdb1a2SPaul Winder 	itrq->itrq_intr_poll = B_FALSE;
45847fdb1a2SPaul Winder 	mutex_exit(&itrq->itrq_rx_lock);
459f2f3bb8fSRobert Mustacchi 
460f2f3bb8fSRobert Mustacchi 	return (0);
461f2f3bb8fSRobert Mustacchi }
462f2f3bb8fSRobert Mustacchi 
463f2f3bb8fSRobert Mustacchi /* ARGSUSED */
464f2f3bb8fSRobert Mustacchi static int
i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)465f2f3bb8fSRobert Mustacchi i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)
466f2f3bb8fSRobert Mustacchi {
467f2f3bb8fSRobert Mustacchi 	i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
468f2f3bb8fSRobert Mustacchi 
46947fdb1a2SPaul Winder 	mutex_enter(&itrq->itrq_rx_lock);
4705b7cbeceSRobert Mustacchi 	i40e_intr_rx_queue_disable(itrq);
47147fdb1a2SPaul Winder 	itrq->itrq_intr_poll = B_TRUE;
47247fdb1a2SPaul Winder 	mutex_exit(&itrq->itrq_rx_lock);
473f2f3bb8fSRobert Mustacchi 
474f2f3bb8fSRobert Mustacchi 	return (0);
475f2f3bb8fSRobert Mustacchi }
476f2f3bb8fSRobert Mustacchi 
477f2f3bb8fSRobert Mustacchi /* ARGSUSED */
478f2f3bb8fSRobert Mustacchi static void
i40e_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)479f2f3bb8fSRobert Mustacchi i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
480f2f3bb8fSRobert Mustacchi     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
481f2f3bb8fSRobert Mustacchi {
482f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
483f2f3bb8fSRobert Mustacchi 	mac_intr_t *mintr = &infop->mri_intr;
484f2f3bb8fSRobert Mustacchi 	i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]);
485f2f3bb8fSRobert Mustacchi 
486f2f3bb8fSRobert Mustacchi 	/*
487f2f3bb8fSRobert Mustacchi 	 * Note the group index here is expected to be -1 due to the fact that
488f2f3bb8fSRobert Mustacchi 	 * we're not actually grouping things tx-wise at this time.
489f2f3bb8fSRobert Mustacchi 	 */
490f2f3bb8fSRobert Mustacchi 	ASSERT(group_index == -1);
491*5ca90d72SRyan Zezeski 	ASSERT(ring_index < i40e->i40e_num_trqpairs_per_vsi);
492f2f3bb8fSRobert Mustacchi 
493f2f3bb8fSRobert Mustacchi 	itrq->itrq_mactxring = rh;
494f2f3bb8fSRobert Mustacchi 	infop->mri_driver = (mac_ring_driver_t)itrq;
495f2f3bb8fSRobert Mustacchi 	infop->mri_start = NULL;
496f2f3bb8fSRobert Mustacchi 	infop->mri_stop = NULL;
497f2f3bb8fSRobert Mustacchi 	infop->mri_tx = i40e_ring_tx;
498f2f3bb8fSRobert Mustacchi 	infop->mri_stat = i40e_tx_ring_stat;
499f2f3bb8fSRobert Mustacchi 
500f2f3bb8fSRobert Mustacchi 	/*
501f2f3bb8fSRobert Mustacchi 	 * We only provide the handle in cases where we have MSI-X interrupts,
502f2f3bb8fSRobert Mustacchi 	 * to indicate that we'd actually support retargetting.
503f2f3bb8fSRobert Mustacchi 	 */
504f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
505f2f3bb8fSRobert Mustacchi 		mintr->mi_ddi_handle =
506f2f3bb8fSRobert Mustacchi 		    i40e->i40e_intr_handles[itrq->itrq_tx_intrvec];
507f2f3bb8fSRobert Mustacchi 	}
508f2f3bb8fSRobert Mustacchi }
509f2f3bb8fSRobert Mustacchi 
510f2f3bb8fSRobert Mustacchi /* ARGSUSED */
511f2f3bb8fSRobert Mustacchi static void
i40e_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)512f2f3bb8fSRobert Mustacchi i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
513f2f3bb8fSRobert Mustacchi     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
514f2f3bb8fSRobert Mustacchi {
515f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
516f2f3bb8fSRobert Mustacchi 	mac_intr_t *mintr = &infop->mri_intr;
517*5ca90d72SRyan Zezeski 	uint_t trqpair_index;
518*5ca90d72SRyan Zezeski 	i40e_trqpair_t *itrq;
519f2f3bb8fSRobert Mustacchi 
520*5ca90d72SRyan Zezeski 	/* This assumes static groups. */
521*5ca90d72SRyan Zezeski 	ASSERT3S(group_index, >=, 0);
522*5ca90d72SRyan Zezeski 	ASSERT3S(ring_index, >=, 0);
523*5ca90d72SRyan Zezeski 	trqpair_index = (group_index * i40e->i40e_num_trqpairs_per_vsi) +
524*5ca90d72SRyan Zezeski 	    ring_index;
525*5ca90d72SRyan Zezeski 	ASSERT3U(trqpair_index, <, i40e->i40e_num_trqpairs);
526*5ca90d72SRyan Zezeski 	itrq = &i40e->i40e_trqpairs[trqpair_index];
527f2f3bb8fSRobert Mustacchi 
528f2f3bb8fSRobert Mustacchi 	itrq->itrq_macrxring = rh;
529f2f3bb8fSRobert Mustacchi 	infop->mri_driver = (mac_ring_driver_t)itrq;
530f2f3bb8fSRobert Mustacchi 	infop->mri_start = i40e_ring_start;
531f2f3bb8fSRobert Mustacchi 	infop->mri_stop = NULL;
532f2f3bb8fSRobert Mustacchi 	infop->mri_poll = i40e_ring_rx_poll;
533f2f3bb8fSRobert Mustacchi 	infop->mri_stat = i40e_rx_ring_stat;
534f2f3bb8fSRobert Mustacchi 	mintr->mi_handle = (mac_intr_handle_t)itrq;
535f2f3bb8fSRobert Mustacchi 	mintr->mi_enable = i40e_rx_ring_intr_enable;
536f2f3bb8fSRobert Mustacchi 	mintr->mi_disable = i40e_rx_ring_intr_disable;
537f2f3bb8fSRobert Mustacchi 
538f2f3bb8fSRobert Mustacchi 	/*
539f2f3bb8fSRobert Mustacchi 	 * We only provide the handle in cases where we have MSI-X interrupts,
540f2f3bb8fSRobert Mustacchi 	 * to indicate that we'd actually support retargetting.
541f2f3bb8fSRobert Mustacchi 	 */
542f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
543f2f3bb8fSRobert Mustacchi 		mintr->mi_ddi_handle =
544f2f3bb8fSRobert Mustacchi 		    i40e->i40e_intr_handles[itrq->itrq_rx_intrvec];
545f2f3bb8fSRobert Mustacchi 	}
546f2f3bb8fSRobert Mustacchi }
547f2f3bb8fSRobert Mustacchi 
548f2f3bb8fSRobert Mustacchi /* ARGSUSED */
549f2f3bb8fSRobert Mustacchi static void
i40e_fill_rx_group(void * arg,mac_ring_type_t rtype,const int index,mac_group_info_t * infop,mac_group_handle_t gh)550f2f3bb8fSRobert Mustacchi i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
551f2f3bb8fSRobert Mustacchi     mac_group_info_t *infop, mac_group_handle_t gh)
552f2f3bb8fSRobert Mustacchi {
553f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
554*5ca90d72SRyan Zezeski 	i40e_rx_group_t *rxg;
555f2f3bb8fSRobert Mustacchi 
556f2f3bb8fSRobert Mustacchi 	if (rtype != MAC_RING_TYPE_RX)
557f2f3bb8fSRobert Mustacchi 		return;
558f2f3bb8fSRobert Mustacchi 
559*5ca90d72SRyan Zezeski 	rxg = &i40e->i40e_rx_groups[index];
560*5ca90d72SRyan Zezeski 	rxg->irg_grp_hdl = gh;
561*5ca90d72SRyan Zezeski 
562*5ca90d72SRyan Zezeski 	infop->mgi_driver = (mac_group_driver_t)rxg;
563f2f3bb8fSRobert Mustacchi 	infop->mgi_start = NULL;
564f2f3bb8fSRobert Mustacchi 	infop->mgi_stop = NULL;
565f2f3bb8fSRobert Mustacchi 	infop->mgi_addmac = i40e_group_add_mac;
566f2f3bb8fSRobert Mustacchi 	infop->mgi_remmac = i40e_group_remove_mac;
567f2f3bb8fSRobert Mustacchi 
568*5ca90d72SRyan Zezeski 	ASSERT(i40e->i40e_num_rx_groups <= I40E_GROUP_MAX);
569*5ca90d72SRyan Zezeski 	infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi;
570f2f3bb8fSRobert Mustacchi }
571f2f3bb8fSRobert Mustacchi 
57248a4016cSRobert Mustacchi static int
i40e_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)57348a4016cSRobert Mustacchi i40e_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
57448a4016cSRobert Mustacchi {
57548a4016cSRobert Mustacchi 	boolean_t present, usable;
57648a4016cSRobert Mustacchi 	i40e_t *i40e = arg;
57748a4016cSRobert Mustacchi 
57848a4016cSRobert Mustacchi 	if (id != 0 || infop == NULL)
57948a4016cSRobert Mustacchi 		return (EINVAL);
58048a4016cSRobert Mustacchi 
58148a4016cSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
5827e6ab961SRobert Mustacchi 	switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
5837e6ab961SRobert Mustacchi 	case I40E_MODULE_TYPE_SFP:
5847e6ab961SRobert Mustacchi 	case I40E_MODULE_TYPE_QSFP:
5857e6ab961SRobert Mustacchi 		break;
5867e6ab961SRobert Mustacchi 	default:
5877e6ab961SRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
5887e6ab961SRobert Mustacchi 		return (ENOTSUP);
5897e6ab961SRobert Mustacchi 	}
5907e6ab961SRobert Mustacchi 
59148a4016cSRobert Mustacchi 	present = !!(i40e->i40e_hw_space.phy.link_info.link_info &
59248a4016cSRobert Mustacchi 	    I40E_AQ_MEDIA_AVAILABLE);
59348a4016cSRobert Mustacchi 	if (present) {
59448a4016cSRobert Mustacchi 		usable = !!(i40e->i40e_hw_space.phy.link_info.an_info &
59548a4016cSRobert Mustacchi 		    I40E_AQ_QUALIFIED_MODULE);
59648a4016cSRobert Mustacchi 	} else {
59748a4016cSRobert Mustacchi 		usable = B_FALSE;
59848a4016cSRobert Mustacchi 	}
59948a4016cSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
60048a4016cSRobert Mustacchi 
60148a4016cSRobert Mustacchi 	mac_transceiver_info_set_usable(infop, usable);
60248a4016cSRobert Mustacchi 	mac_transceiver_info_set_present(infop, present);
60348a4016cSRobert Mustacchi 
60448a4016cSRobert Mustacchi 	return (0);
60548a4016cSRobert Mustacchi }
60648a4016cSRobert Mustacchi 
6074d210590SRobert Mustacchi static int
i40e_transceiver_read(void * arg,uint_t id,uint_t page,void * buf,size_t nbytes,off_t offset,size_t * nread)6087e6ab961SRobert Mustacchi i40e_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
6097e6ab961SRobert Mustacchi     size_t nbytes, off_t offset, size_t *nread)
6107e6ab961SRobert Mustacchi {
6117e6ab961SRobert Mustacchi 	i40e_t *i40e = arg;
6127e6ab961SRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
6137e6ab961SRobert Mustacchi 	uint8_t *buf8 = buf;
6147e6ab961SRobert Mustacchi 	size_t i;
6157e6ab961SRobert Mustacchi 
6167e6ab961SRobert Mustacchi 	if (id != 0 || buf == NULL || nbytes == 0 || nread == NULL ||
6177e6ab961SRobert Mustacchi 	    (page != 0xa0 && page != 0xa2) || offset < 0)
6187e6ab961SRobert Mustacchi 		return (EINVAL);
6197e6ab961SRobert Mustacchi 
6207e6ab961SRobert Mustacchi 	/*
6217e6ab961SRobert Mustacchi 	 * Both supported pages have a length of 256 bytes, ensure nothing asks
6227e6ab961SRobert Mustacchi 	 * us to go beyond that.
6237e6ab961SRobert Mustacchi 	 */
6247e6ab961SRobert Mustacchi 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
6257e6ab961SRobert Mustacchi 		return (EINVAL);
6267e6ab961SRobert Mustacchi 	}
6277e6ab961SRobert Mustacchi 
6287e6ab961SRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
6297e6ab961SRobert Mustacchi 	switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
6307e6ab961SRobert Mustacchi 	case I40E_MODULE_TYPE_SFP:
6317e6ab961SRobert Mustacchi 	case I40E_MODULE_TYPE_QSFP:
6327e6ab961SRobert Mustacchi 		break;
6337e6ab961SRobert Mustacchi 	default:
6347e6ab961SRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
6357e6ab961SRobert Mustacchi 		return (ENOTSUP);
6367e6ab961SRobert Mustacchi 	}
6377e6ab961SRobert Mustacchi 
6387e6ab961SRobert Mustacchi 	/*
6397e6ab961SRobert Mustacchi 	 * Make sure we have a sufficiently new firmware version to run this
6407e6ab961SRobert Mustacchi 	 * command. This was introduced in firmware API 1.7. This is apparently
6417e6ab961SRobert Mustacchi 	 * only supported on the XL710 MAC, not the XL722.
6427e6ab961SRobert Mustacchi 	 */
6437e6ab961SRobert Mustacchi 	if (hw->mac.type != I40E_MAC_XL710 || hw->aq.api_maj_ver != 1 ||
6447e6ab961SRobert Mustacchi 	    hw->aq.api_min_ver < 7) {
6457e6ab961SRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
6467e6ab961SRobert Mustacchi 		return (ENOTSUP);
6477e6ab961SRobert Mustacchi 	}
6487e6ab961SRobert Mustacchi 
6497e6ab961SRobert Mustacchi 	for (i = 0; i < nbytes; i++, offset++) {
6507e6ab961SRobert Mustacchi 		enum i40e_status_code status;
6517e6ab961SRobert Mustacchi 		uint32_t val;
6527e6ab961SRobert Mustacchi 
6537e6ab961SRobert Mustacchi 		status = i40e_aq_get_phy_register(hw,
6547e6ab961SRobert Mustacchi 		    I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, page, offset,
6557e6ab961SRobert Mustacchi 		    &val, NULL);
6567e6ab961SRobert Mustacchi 		if (status != I40E_SUCCESS) {
6577e6ab961SRobert Mustacchi 			mutex_exit(&i40e->i40e_general_lock);
6587e6ab961SRobert Mustacchi 			return (EIO);
6597e6ab961SRobert Mustacchi 		}
6607e6ab961SRobert Mustacchi 
6617e6ab961SRobert Mustacchi 		buf8[i] = (uint8_t)val;
6627e6ab961SRobert Mustacchi 	}
6637e6ab961SRobert Mustacchi 
6647e6ab961SRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
6657e6ab961SRobert Mustacchi 	*nread = nbytes;
6667e6ab961SRobert Mustacchi 
6677e6ab961SRobert Mustacchi 	return (0);
6687e6ab961SRobert Mustacchi }
6697e6ab961SRobert Mustacchi 
6707e6ab961SRobert Mustacchi static int
i40e_gld_led_set(void * arg,mac_led_mode_t mode,uint_t flags)6714d210590SRobert Mustacchi i40e_gld_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
6724d210590SRobert Mustacchi {
6734d210590SRobert Mustacchi 	i40e_t *i40e = arg;
6744d210590SRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
6754d210590SRobert Mustacchi 
6764d210590SRobert Mustacchi 	if (flags != 0)
6774d210590SRobert Mustacchi 		return (EINVAL);
6784d210590SRobert Mustacchi 
6794d210590SRobert Mustacchi 	if (mode != MAC_LED_DEFAULT &&
6804d210590SRobert Mustacchi 	    mode != MAC_LED_IDENT &&
6814d210590SRobert Mustacchi 	    mode != MAC_LED_OFF &&
6824d210590SRobert Mustacchi 	    mode != MAC_LED_ON)
6834d210590SRobert Mustacchi 		return (ENOTSUP);
6844d210590SRobert Mustacchi 
6854d210590SRobert Mustacchi 	if (mode != MAC_LED_DEFAULT && !i40e->i40e_led_saved) {
6864d210590SRobert Mustacchi 		i40e->i40e_led_status = i40e_led_get(hw);
6874d210590SRobert Mustacchi 		i40e->i40e_led_saved = B_TRUE;
6884d210590SRobert Mustacchi 	}
6894d210590SRobert Mustacchi 
6904d210590SRobert Mustacchi 	switch (mode) {
6914d210590SRobert Mustacchi 	case MAC_LED_DEFAULT:
6924d210590SRobert Mustacchi 		if (i40e->i40e_led_saved) {
6934d210590SRobert Mustacchi 			i40e_led_set(hw, i40e->i40e_led_status, B_FALSE);
6944d210590SRobert Mustacchi 			i40e->i40e_led_status = 0;
6954d210590SRobert Mustacchi 			i40e->i40e_led_saved = B_FALSE;
6964d210590SRobert Mustacchi 		}
6974d210590SRobert Mustacchi 		break;
6984d210590SRobert Mustacchi 	case MAC_LED_IDENT:
6994d210590SRobert Mustacchi 		i40e_led_set(hw, 0xf, B_TRUE);
7004d210590SRobert Mustacchi 		break;
7014d210590SRobert Mustacchi 	case MAC_LED_OFF:
7024d210590SRobert Mustacchi 		i40e_led_set(hw, 0x0, B_FALSE);
7034d210590SRobert Mustacchi 		break;
7044d210590SRobert Mustacchi 	case MAC_LED_ON:
7054d210590SRobert Mustacchi 		i40e_led_set(hw, 0xf, B_FALSE);
7064d210590SRobert Mustacchi 		break;
7074d210590SRobert Mustacchi 	default:
7084d210590SRobert Mustacchi 		return (ENOTSUP);
7094d210590SRobert Mustacchi 	}
7104d210590SRobert Mustacchi 
7114d210590SRobert Mustacchi 	return (0);
7124d210590SRobert Mustacchi }
7134d210590SRobert Mustacchi 
714f2f3bb8fSRobert Mustacchi static boolean_t
i40e_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)715f2f3bb8fSRobert Mustacchi i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
716f2f3bb8fSRobert Mustacchi {
717f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
718f2f3bb8fSRobert Mustacchi 	mac_capab_rings_t *cap_rings;
71948a4016cSRobert Mustacchi 	mac_capab_transceiver_t *mct;
7204d210590SRobert Mustacchi 	mac_capab_led_t *mcl;
721f2f3bb8fSRobert Mustacchi 
722f2f3bb8fSRobert Mustacchi 	switch (cap) {
723f2f3bb8fSRobert Mustacchi 	case MAC_CAPAB_HCKSUM: {
724f2f3bb8fSRobert Mustacchi 		uint32_t *txflags = cap_data;
725f2f3bb8fSRobert Mustacchi 
726f2f3bb8fSRobert Mustacchi 		*txflags = 0;
727f2f3bb8fSRobert Mustacchi 		if (i40e->i40e_tx_hcksum_enable == B_TRUE)
728f2f3bb8fSRobert Mustacchi 			*txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
729f2f3bb8fSRobert Mustacchi 		break;
730f2f3bb8fSRobert Mustacchi 	}
731f2f3bb8fSRobert Mustacchi 
732*5ca90d72SRyan Zezeski 	case MAC_CAPAB_LSO: {
733*5ca90d72SRyan Zezeski 		mac_capab_lso_t *cap_lso = cap_data;
734*5ca90d72SRyan Zezeski 
735*5ca90d72SRyan Zezeski 		if (i40e->i40e_tx_lso_enable == B_TRUE) {
736*5ca90d72SRyan Zezeski 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
737*5ca90d72SRyan Zezeski 			cap_lso->lso_basic_tcp_ipv4.lso_max = I40E_LSO_MAXLEN;
738*5ca90d72SRyan Zezeski 		} else {
739*5ca90d72SRyan Zezeski 			return (B_FALSE);
740*5ca90d72SRyan Zezeski 		}
741*5ca90d72SRyan Zezeski 		break;
742*5ca90d72SRyan Zezeski 	}
743*5ca90d72SRyan Zezeski 
744f2f3bb8fSRobert Mustacchi 	case MAC_CAPAB_RINGS:
745f2f3bb8fSRobert Mustacchi 		cap_rings = cap_data;
746f2f3bb8fSRobert Mustacchi 		cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
747f2f3bb8fSRobert Mustacchi 		switch (cap_rings->mr_type) {
748f2f3bb8fSRobert Mustacchi 		case MAC_RING_TYPE_TX:
749f2f3bb8fSRobert Mustacchi 			/*
750*5ca90d72SRyan Zezeski 			 * Note, saying we have no groups, but some
751*5ca90d72SRyan Zezeski 			 * number of rings indicates to MAC that it
752*5ca90d72SRyan Zezeski 			 * should create psuedo-groups with one for
753*5ca90d72SRyan Zezeski 			 * each TX ring. This may not be the long term
754*5ca90d72SRyan Zezeski 			 * behavior we want, but it'll work for now.
755f2f3bb8fSRobert Mustacchi 			 */
756f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gnum = 0;
757*5ca90d72SRyan Zezeski 			cap_rings->mr_rnum = i40e->i40e_num_trqpairs_per_vsi;
758f2f3bb8fSRobert Mustacchi 			cap_rings->mr_rget = i40e_fill_tx_ring;
759f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gget = NULL;
760f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gaddring = NULL;
761f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gremring = NULL;
762f2f3bb8fSRobert Mustacchi 			break;
763f2f3bb8fSRobert Mustacchi 		case MAC_RING_TYPE_RX:
764f2f3bb8fSRobert Mustacchi 			cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
765f2f3bb8fSRobert Mustacchi 			cap_rings->mr_rget = i40e_fill_rx_ring;
766*5ca90d72SRyan Zezeski 			cap_rings->mr_gnum = i40e->i40e_num_rx_groups;
767f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gget = i40e_fill_rx_group;
768f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gaddring = NULL;
769f2f3bb8fSRobert Mustacchi 			cap_rings->mr_gremring = NULL;
770f2f3bb8fSRobert Mustacchi 			break;
771f2f3bb8fSRobert Mustacchi 		default:
772f2f3bb8fSRobert Mustacchi 			return (B_FALSE);
773f2f3bb8fSRobert Mustacchi 		}
774f2f3bb8fSRobert Mustacchi 		break;
77548a4016cSRobert Mustacchi 	case MAC_CAPAB_TRANSCEIVER:
77648a4016cSRobert Mustacchi 		mct = cap_data;
77748a4016cSRobert Mustacchi 
77848a4016cSRobert Mustacchi 		/*
77948a4016cSRobert Mustacchi 		 * Firmware doesn't have a great way of telling us in advance
78048a4016cSRobert Mustacchi 		 * whether we'd expect a SFF transceiver. As such, we always
78148a4016cSRobert Mustacchi 		 * advertise the support for this capability.
78248a4016cSRobert Mustacchi 		 */
78348a4016cSRobert Mustacchi 		mct->mct_flags = 0;
78448a4016cSRobert Mustacchi 		mct->mct_ntransceivers = 1;
78548a4016cSRobert Mustacchi 		mct->mct_info = i40e_transceiver_info;
7867e6ab961SRobert Mustacchi 		mct->mct_read = i40e_transceiver_read;
78748a4016cSRobert Mustacchi 
78848a4016cSRobert Mustacchi 		return (B_TRUE);
7894d210590SRobert Mustacchi 	case MAC_CAPAB_LED:
7904d210590SRobert Mustacchi 		mcl = cap_data;
7914d210590SRobert Mustacchi 
7924d210590SRobert Mustacchi 		mcl->mcl_flags = 0;
7934d210590SRobert Mustacchi 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT | MAC_LED_OFF |
7944d210590SRobert Mustacchi 		    MAC_LED_ON;
7954d210590SRobert Mustacchi 		mcl->mcl_set = i40e_gld_led_set;
7964d210590SRobert Mustacchi 		break;
7974d210590SRobert Mustacchi 
798f2f3bb8fSRobert Mustacchi 	default:
799f2f3bb8fSRobert Mustacchi 		return (B_FALSE);
800f2f3bb8fSRobert Mustacchi 	}
801f2f3bb8fSRobert Mustacchi 
802f2f3bb8fSRobert Mustacchi 	return (B_TRUE);
803f2f3bb8fSRobert Mustacchi }
804f2f3bb8fSRobert Mustacchi 
805f2f3bb8fSRobert Mustacchi /* ARGSUSED */
806f2f3bb8fSRobert Mustacchi static int
i40e_m_setprop_private(i40e_t * i40e,const char * pr_name,uint_t pr_valsize,const void * pr_val)807f2f3bb8fSRobert Mustacchi i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
808f2f3bb8fSRobert Mustacchi     const void *pr_val)
809f2f3bb8fSRobert Mustacchi {
810f2f3bb8fSRobert Mustacchi 	int ret;
811f2f3bb8fSRobert Mustacchi 	long val;
812f2f3bb8fSRobert Mustacchi 	char *eptr;
813f2f3bb8fSRobert Mustacchi 
814f2f3bb8fSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
815f2f3bb8fSRobert Mustacchi 
816f2f3bb8fSRobert Mustacchi 	if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
817f2f3bb8fSRobert Mustacchi 	    *eptr != '\0') {
818f2f3bb8fSRobert Mustacchi 		return (ret);
819f2f3bb8fSRobert Mustacchi 	}
820f2f3bb8fSRobert Mustacchi 
821f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
822f2f3bb8fSRobert Mustacchi 		if (val < I40E_MIN_RX_DMA_THRESH ||
823f2f3bb8fSRobert Mustacchi 		    val > I40E_MAX_RX_DMA_THRESH) {
824f2f3bb8fSRobert Mustacchi 			return (EINVAL);
825f2f3bb8fSRobert Mustacchi 		}
826f2f3bb8fSRobert Mustacchi 		i40e->i40e_rx_dma_min = (uint32_t)val;
827f2f3bb8fSRobert Mustacchi 		return (0);
828f2f3bb8fSRobert Mustacchi 	}
829f2f3bb8fSRobert Mustacchi 
830f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
831f2f3bb8fSRobert Mustacchi 		if (val < I40E_MIN_TX_DMA_THRESH ||
832f2f3bb8fSRobert Mustacchi 		    val > I40E_MAX_TX_DMA_THRESH) {
833f2f3bb8fSRobert Mustacchi 			return (EINVAL);
834f2f3bb8fSRobert Mustacchi 		}
835f2f3bb8fSRobert Mustacchi 		i40e->i40e_tx_dma_min = (uint32_t)val;
836f2f3bb8fSRobert Mustacchi 		return (0);
837f2f3bb8fSRobert Mustacchi 	}
838f2f3bb8fSRobert Mustacchi 
839f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
840f2f3bb8fSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
841f2f3bb8fSRobert Mustacchi 		    val > I40E_MAX_ITR) {
842f2f3bb8fSRobert Mustacchi 			return (EINVAL);
843f2f3bb8fSRobert Mustacchi 		}
844f2f3bb8fSRobert Mustacchi 		i40e->i40e_rx_itr = (uint32_t)val;
845f2f3bb8fSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
846f2f3bb8fSRobert Mustacchi 		return (0);
847f2f3bb8fSRobert Mustacchi 	}
848f2f3bb8fSRobert Mustacchi 
849f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
850f2f3bb8fSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
851f2f3bb8fSRobert Mustacchi 		    val > I40E_MAX_ITR) {
852f2f3bb8fSRobert Mustacchi 			return (EINVAL);
853f2f3bb8fSRobert Mustacchi 		}
854f2f3bb8fSRobert Mustacchi 		i40e->i40e_tx_itr = (uint32_t)val;
855f2f3bb8fSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
856f2f3bb8fSRobert Mustacchi 		return (0);
857f2f3bb8fSRobert Mustacchi 	}
858f2f3bb8fSRobert Mustacchi 
859f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
860f2f3bb8fSRobert Mustacchi 		if (val < I40E_MIN_ITR ||
861f2f3bb8fSRobert Mustacchi 		    val > I40E_MAX_ITR) {
862f2f3bb8fSRobert Mustacchi 			return (EINVAL);
863f2f3bb8fSRobert Mustacchi 		}
864f2f3bb8fSRobert Mustacchi 		i40e->i40e_tx_itr = (uint32_t)val;
865f2f3bb8fSRobert Mustacchi 		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
866f2f3bb8fSRobert Mustacchi 		    i40e->i40e_other_itr);
867f2f3bb8fSRobert Mustacchi 		return (0);
868f2f3bb8fSRobert Mustacchi 	}
869f2f3bb8fSRobert Mustacchi 
870f2f3bb8fSRobert Mustacchi 	return (ENOTSUP);
871f2f3bb8fSRobert Mustacchi }
872f2f3bb8fSRobert Mustacchi 
873f2f3bb8fSRobert Mustacchi static int
i40e_m_getprop_private(i40e_t * i40e,const char * pr_name,uint_t pr_valsize,void * pr_val)874f2f3bb8fSRobert Mustacchi i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
875f2f3bb8fSRobert Mustacchi     void *pr_val)
876f2f3bb8fSRobert Mustacchi {
877f2f3bb8fSRobert Mustacchi 	uint32_t val;
878f2f3bb8fSRobert Mustacchi 
879f2f3bb8fSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
880f2f3bb8fSRobert Mustacchi 
881f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
882f2f3bb8fSRobert Mustacchi 		val = i40e->i40e_rx_dma_min;
883f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
884f2f3bb8fSRobert Mustacchi 		val = i40e->i40e_tx_dma_min;
885f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
886f2f3bb8fSRobert Mustacchi 		val = i40e->i40e_rx_itr;
887f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
888f2f3bb8fSRobert Mustacchi 		val = i40e->i40e_tx_itr;
889f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
890f2f3bb8fSRobert Mustacchi 		val = i40e->i40e_other_itr;
891f2f3bb8fSRobert Mustacchi 	} else {
892f2f3bb8fSRobert Mustacchi 		return (ENOTSUP);
893f2f3bb8fSRobert Mustacchi 	}
894f2f3bb8fSRobert Mustacchi 
895f2f3bb8fSRobert Mustacchi 	if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
896f2f3bb8fSRobert Mustacchi 		return (ERANGE);
897f2f3bb8fSRobert Mustacchi 	return (0);
898f2f3bb8fSRobert Mustacchi }
899f2f3bb8fSRobert Mustacchi 
900f2f3bb8fSRobert Mustacchi /*
901f2f3bb8fSRobert Mustacchi  * Annoyingly for private properties MAC seems to ignore default values that
902f2f3bb8fSRobert Mustacchi  * aren't strings. That means that we have to translate all of these into
903f2f3bb8fSRobert Mustacchi  * uint32_t's and instead we size the buffer to be large enough to hold a
904f2f3bb8fSRobert Mustacchi  * uint32_t.
905f2f3bb8fSRobert Mustacchi  */
906f2f3bb8fSRobert Mustacchi /* ARGSUSED */
907f2f3bb8fSRobert Mustacchi static void
i40e_m_propinfo_private(i40e_t * i40e,const char * pr_name,mac_prop_info_handle_t prh)908f2f3bb8fSRobert Mustacchi i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name,
909f2f3bb8fSRobert Mustacchi     mac_prop_info_handle_t prh)
910f2f3bb8fSRobert Mustacchi {
911f2f3bb8fSRobert Mustacchi 	char buf[64];
912f2f3bb8fSRobert Mustacchi 	uint32_t def;
913f2f3bb8fSRobert Mustacchi 
914f2f3bb8fSRobert Mustacchi 	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
915f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
916f2f3bb8fSRobert Mustacchi 		def = I40E_DEF_RX_DMA_THRESH;
917f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh,
918f2f3bb8fSRobert Mustacchi 		    I40E_MIN_RX_DMA_THRESH,
919f2f3bb8fSRobert Mustacchi 		    I40E_MAX_RX_DMA_THRESH);
920f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
921f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
922f2f3bb8fSRobert Mustacchi 		def = I40E_DEF_TX_DMA_THRESH;
923f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh,
924f2f3bb8fSRobert Mustacchi 		    I40E_MIN_TX_DMA_THRESH,
925f2f3bb8fSRobert Mustacchi 		    I40E_MAX_TX_DMA_THRESH);
926f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
927f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
928f2f3bb8fSRobert Mustacchi 		def = I40E_DEF_RX_ITR;
929f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
930f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
931f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
932f2f3bb8fSRobert Mustacchi 		def = I40E_DEF_TX_ITR;
933f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
934f2f3bb8fSRobert Mustacchi 	} else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
935f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
936f2f3bb8fSRobert Mustacchi 		def = I40E_DEF_OTHER_ITR;
937f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
938f2f3bb8fSRobert Mustacchi 	} else {
939f2f3bb8fSRobert Mustacchi 		return;
940f2f3bb8fSRobert Mustacchi 	}
941f2f3bb8fSRobert Mustacchi 
942f2f3bb8fSRobert Mustacchi 	(void) snprintf(buf, sizeof (buf), "%d", def);
943f2f3bb8fSRobert Mustacchi 	mac_prop_info_set_default_str(prh, buf);
944f2f3bb8fSRobert Mustacchi }
945f2f3bb8fSRobert Mustacchi 
946f2f3bb8fSRobert Mustacchi static int
i40e_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)947f2f3bb8fSRobert Mustacchi i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
948f2f3bb8fSRobert Mustacchi     uint_t pr_valsize, const void *pr_val)
949f2f3bb8fSRobert Mustacchi {
950f2f3bb8fSRobert Mustacchi 	uint32_t new_mtu;
951f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
952f2f3bb8fSRobert Mustacchi 	int ret = 0;
953f2f3bb8fSRobert Mustacchi 
954f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
955f2f3bb8fSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
956f2f3bb8fSRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
957f2f3bb8fSRobert Mustacchi 		return (ECANCELED);
958f2f3bb8fSRobert Mustacchi 	}
959f2f3bb8fSRobert Mustacchi 
960f2f3bb8fSRobert Mustacchi 	switch (pr_num) {
961f2f3bb8fSRobert Mustacchi 	/*
962f2f3bb8fSRobert Mustacchi 	 * These properties are always read-only across every device.
963f2f3bb8fSRobert Mustacchi 	 */
964f2f3bb8fSRobert Mustacchi 	case MAC_PROP_DUPLEX:
965f2f3bb8fSRobert Mustacchi 	case MAC_PROP_SPEED:
966f2f3bb8fSRobert Mustacchi 	case MAC_PROP_STATUS:
967f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
968f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
969f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
9708f179fb3SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
971f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
972f2f3bb8fSRobert Mustacchi 		ret = ENOTSUP;
973f2f3bb8fSRobert Mustacchi 		break;
974f2f3bb8fSRobert Mustacchi 	/*
975f2f3bb8fSRobert Mustacchi 	 * These are read-only at this time as we don't support configuring
976f2f3bb8fSRobert Mustacchi 	 * auto-negotiation. See the theory statement in i40e_main.c.
977f2f3bb8fSRobert Mustacchi 	 */
978f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
979f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
980f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
9818f179fb3SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
982f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
983f2f3bb8fSRobert Mustacchi 	case MAC_PROP_AUTONEG:
984f2f3bb8fSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
985f2f3bb8fSRobert Mustacchi 		ret = ENOTSUP;
986f2f3bb8fSRobert Mustacchi 		break;
987f2f3bb8fSRobert Mustacchi 
988f2f3bb8fSRobert Mustacchi 	case MAC_PROP_MTU:
989f2f3bb8fSRobert Mustacchi 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
990f2f3bb8fSRobert Mustacchi 		if (new_mtu == i40e->i40e_sdu)
991f2f3bb8fSRobert Mustacchi 			break;
992f2f3bb8fSRobert Mustacchi 
993f2f3bb8fSRobert Mustacchi 		if (new_mtu < I40E_MIN_MTU ||
994f2f3bb8fSRobert Mustacchi 		    new_mtu > I40E_MAX_MTU) {
995f2f3bb8fSRobert Mustacchi 			ret = EINVAL;
996f2f3bb8fSRobert Mustacchi 			break;
997f2f3bb8fSRobert Mustacchi 		}
998f2f3bb8fSRobert Mustacchi 
999f2f3bb8fSRobert Mustacchi 		if (i40e->i40e_state & I40E_STARTED) {
1000f2f3bb8fSRobert Mustacchi 			ret = EBUSY;
1001f2f3bb8fSRobert Mustacchi 			break;
1002f2f3bb8fSRobert Mustacchi 		}
1003f2f3bb8fSRobert Mustacchi 
1004f2f3bb8fSRobert Mustacchi 		ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu);
1005f2f3bb8fSRobert Mustacchi 		if (ret == 0) {
1006f2f3bb8fSRobert Mustacchi 			i40e->i40e_sdu = new_mtu;
1007f2f3bb8fSRobert Mustacchi 			i40e_update_mtu(i40e);
1008f2f3bb8fSRobert Mustacchi 		}
1009f2f3bb8fSRobert Mustacchi 		break;
1010f2f3bb8fSRobert Mustacchi 
1011f2f3bb8fSRobert Mustacchi 	case MAC_PROP_PRIVATE:
1012f2f3bb8fSRobert Mustacchi 		ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val);
1013f2f3bb8fSRobert Mustacchi 		break;
1014f2f3bb8fSRobert Mustacchi 	default:
1015f2f3bb8fSRobert Mustacchi 		ret = ENOTSUP;
1016f2f3bb8fSRobert Mustacchi 		break;
1017f2f3bb8fSRobert Mustacchi 	}
1018f2f3bb8fSRobert Mustacchi 
1019f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1020f2f3bb8fSRobert Mustacchi 	return (ret);
1021f2f3bb8fSRobert Mustacchi }
1022f2f3bb8fSRobert Mustacchi 
1023f2f3bb8fSRobert Mustacchi static int
i40e_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)1024f2f3bb8fSRobert Mustacchi i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1025f2f3bb8fSRobert Mustacchi     uint_t pr_valsize, void *pr_val)
1026f2f3bb8fSRobert Mustacchi {
1027f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
1028f2f3bb8fSRobert Mustacchi 	uint64_t speed;
1029f2f3bb8fSRobert Mustacchi 	int ret = 0;
1030f2f3bb8fSRobert Mustacchi 	uint8_t *u8;
1031f2f3bb8fSRobert Mustacchi 	link_flowctrl_t fctl;
1032f2f3bb8fSRobert Mustacchi 
1033f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
1034f2f3bb8fSRobert Mustacchi 
1035f2f3bb8fSRobert Mustacchi 	switch (pr_num) {
1036f2f3bb8fSRobert Mustacchi 	case MAC_PROP_DUPLEX:
1037f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (link_duplex_t)) {
1038f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1039f2f3bb8fSRobert Mustacchi 			break;
1040f2f3bb8fSRobert Mustacchi 		}
1041f2f3bb8fSRobert Mustacchi 		bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t));
1042f2f3bb8fSRobert Mustacchi 		break;
1043f2f3bb8fSRobert Mustacchi 	case MAC_PROP_SPEED:
1044f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint64_t)) {
1045f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1046f2f3bb8fSRobert Mustacchi 			break;
1047f2f3bb8fSRobert Mustacchi 		}
1048f2f3bb8fSRobert Mustacchi 		speed = i40e->i40e_link_speed * 1000000ULL;
1049f2f3bb8fSRobert Mustacchi 		bcopy(&speed, pr_val, sizeof (speed));
1050f2f3bb8fSRobert Mustacchi 		break;
1051f2f3bb8fSRobert Mustacchi 	case MAC_PROP_STATUS:
1052f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (link_state_t)) {
1053f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1054f2f3bb8fSRobert Mustacchi 			break;
1055f2f3bb8fSRobert Mustacchi 		}
1056f2f3bb8fSRobert Mustacchi 		bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t));
1057f2f3bb8fSRobert Mustacchi 		break;
1058f2f3bb8fSRobert Mustacchi 	case MAC_PROP_AUTONEG:
1059f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
1060f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1061f2f3bb8fSRobert Mustacchi 			break;
1062f2f3bb8fSRobert Mustacchi 		}
1063f2f3bb8fSRobert Mustacchi 		u8 = pr_val;
1064f2f3bb8fSRobert Mustacchi 		*u8 = 1;
1065f2f3bb8fSRobert Mustacchi 		break;
1066f2f3bb8fSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
1067f2f3bb8fSRobert Mustacchi 		/*
1068f2f3bb8fSRobert Mustacchi 		 * Because we don't currently support hardware flow control, we
1069f2f3bb8fSRobert Mustacchi 		 * just hardcode this to be none.
1070f2f3bb8fSRobert Mustacchi 		 */
1071f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (link_flowctrl_t)) {
1072f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1073f2f3bb8fSRobert Mustacchi 			break;
1074f2f3bb8fSRobert Mustacchi 		}
1075f2f3bb8fSRobert Mustacchi 		fctl = LINK_FLOWCTRL_NONE;
1076f2f3bb8fSRobert Mustacchi 		bcopy(&fctl, pr_val, sizeof (link_flowctrl_t));
1077f2f3bb8fSRobert Mustacchi 		break;
1078f2f3bb8fSRobert Mustacchi 	case MAC_PROP_MTU:
1079f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint32_t)) {
1080f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1081f2f3bb8fSRobert Mustacchi 			break;
1082f2f3bb8fSRobert Mustacchi 		}
1083f2f3bb8fSRobert Mustacchi 		bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t));
1084f2f3bb8fSRobert Mustacchi 		break;
1085f2f3bb8fSRobert Mustacchi 
1086f2f3bb8fSRobert Mustacchi 	/*
1087f2f3bb8fSRobert Mustacchi 	 * Because we don't let users control the speeds we may auto-negotiate
1088f2f3bb8fSRobert Mustacchi 	 * to, the values of the ADV_ and EN_ will always be the same.
1089f2f3bb8fSRobert Mustacchi 	 */
1090f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
1091f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
1092f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
1093f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1094f2f3bb8fSRobert Mustacchi 			break;
1095f2f3bb8fSRobert Mustacchi 		}
1096f2f3bb8fSRobert Mustacchi 		u8 = pr_val;
1097f2f3bb8fSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0;
1098f2f3bb8fSRobert Mustacchi 		break;
1099f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
1100f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
1101f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
1102f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1103f2f3bb8fSRobert Mustacchi 			break;
1104f2f3bb8fSRobert Mustacchi 		}
1105f2f3bb8fSRobert Mustacchi 		u8 = pr_val;
1106f2f3bb8fSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0;
1107f2f3bb8fSRobert Mustacchi 		break;
1108f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
1109f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
1110f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
1111f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1112f2f3bb8fSRobert Mustacchi 			break;
1113f2f3bb8fSRobert Mustacchi 		}
1114f2f3bb8fSRobert Mustacchi 		u8 = pr_val;
1115f2f3bb8fSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0;
1116f2f3bb8fSRobert Mustacchi 		break;
11178f179fb3SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
11188f179fb3SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
11198f179fb3SRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
11208f179fb3SRobert Mustacchi 			ret = EOVERFLOW;
11218f179fb3SRobert Mustacchi 			break;
11228f179fb3SRobert Mustacchi 		}
11238f179fb3SRobert Mustacchi 		u8 = pr_val;
11248f179fb3SRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0;
11258f179fb3SRobert Mustacchi 		break;
1126f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
1127f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
1128f2f3bb8fSRobert Mustacchi 		if (pr_valsize < sizeof (uint8_t)) {
1129f2f3bb8fSRobert Mustacchi 			ret = EOVERFLOW;
1130f2f3bb8fSRobert Mustacchi 			break;
1131f2f3bb8fSRobert Mustacchi 		}
1132f2f3bb8fSRobert Mustacchi 		u8 = pr_val;
1133f2f3bb8fSRobert Mustacchi 		*u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0;
1134f2f3bb8fSRobert Mustacchi 		break;
1135f2f3bb8fSRobert Mustacchi 	case MAC_PROP_PRIVATE:
1136f2f3bb8fSRobert Mustacchi 		ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val);
1137f2f3bb8fSRobert Mustacchi 		break;
1138f2f3bb8fSRobert Mustacchi 	default:
1139f2f3bb8fSRobert Mustacchi 		ret = ENOTSUP;
1140f2f3bb8fSRobert Mustacchi 		break;
1141f2f3bb8fSRobert Mustacchi 	}
1142f2f3bb8fSRobert Mustacchi 
1143f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1144f2f3bb8fSRobert Mustacchi 
1145f2f3bb8fSRobert Mustacchi 	return (ret);
1146f2f3bb8fSRobert Mustacchi }
1147f2f3bb8fSRobert Mustacchi 
1148f2f3bb8fSRobert Mustacchi static void
i40e_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)1149f2f3bb8fSRobert Mustacchi i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1150f2f3bb8fSRobert Mustacchi     mac_prop_info_handle_t prh)
1151f2f3bb8fSRobert Mustacchi {
1152f2f3bb8fSRobert Mustacchi 	i40e_t *i40e = arg;
1153f2f3bb8fSRobert Mustacchi 
1154f2f3bb8fSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
1155f2f3bb8fSRobert Mustacchi 
1156f2f3bb8fSRobert Mustacchi 	switch (pr_num) {
1157f2f3bb8fSRobert Mustacchi 	case MAC_PROP_DUPLEX:
1158f2f3bb8fSRobert Mustacchi 	case MAC_PROP_SPEED:
1159f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1160f2f3bb8fSRobert Mustacchi 		break;
1161f2f3bb8fSRobert Mustacchi 	case MAC_PROP_FLOWCTRL:
1162f2f3bb8fSRobert Mustacchi 		/*
1163f2f3bb8fSRobert Mustacchi 		 * At the moment, the driver doesn't support flow control, hence
1164f2f3bb8fSRobert Mustacchi 		 * why this is set to read-only and none.
1165f2f3bb8fSRobert Mustacchi 		 */
1166f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1167f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_link_flowctrl(prh,
1168f2f3bb8fSRobert Mustacchi 		    LINK_FLOWCTRL_NONE);
1169f2f3bb8fSRobert Mustacchi 		break;
1170f2f3bb8fSRobert Mustacchi 	case MAC_PROP_MTU:
1171f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU);
1172f2f3bb8fSRobert Mustacchi 		break;
1173f2f3bb8fSRobert Mustacchi 
1174f2f3bb8fSRobert Mustacchi 	/*
1175f2f3bb8fSRobert Mustacchi 	 * We set the defaults for these based upon the phy's ability to
1176f2f3bb8fSRobert Mustacchi 	 * support the speeds. Note, auto-negotiation is required for fiber,
1177f2f3bb8fSRobert Mustacchi 	 * hence it is read-only and always enabled. When we have access to
1178f2f3bb8fSRobert Mustacchi 	 * copper phys we can revisit this.
1179f2f3bb8fSRobert Mustacchi 	 */
1180f2f3bb8fSRobert Mustacchi 	case MAC_PROP_AUTONEG:
1181f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1182f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh, 1);
1183f2f3bb8fSRobert Mustacchi 		break;
1184f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_100FDX_CAP:
1185f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1186f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1187f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1188f2f3bb8fSRobert Mustacchi 		break;
1189f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_100FDX_CAP:
1190f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1191f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1192f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1193f2f3bb8fSRobert Mustacchi 		break;
1194f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_1000FDX_CAP:
1195f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1196f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1197f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1198f2f3bb8fSRobert Mustacchi 		break;
1199f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_1000FDX_CAP:
1200f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1201f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1202f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1203f2f3bb8fSRobert Mustacchi 		break;
1204f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_10GFDX_CAP:
1205f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1206f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1207f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1208f2f3bb8fSRobert Mustacchi 		break;
1209f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_10GFDX_CAP:
1210f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1211f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1212f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1213f2f3bb8fSRobert Mustacchi 		break;
12148f179fb3SRobert Mustacchi 	case MAC_PROP_ADV_25GFDX_CAP:
12158f179fb3SRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
12168f179fb3SRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
12178f179fb3SRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
12188f179fb3SRobert Mustacchi 		break;
12198f179fb3SRobert Mustacchi 	case MAC_PROP_EN_25GFDX_CAP:
12208f179fb3SRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
12218f179fb3SRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
12228f179fb3SRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
12238f179fb3SRobert Mustacchi 		break;
1224f2f3bb8fSRobert Mustacchi 	case MAC_PROP_ADV_40GFDX_CAP:
1225f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1226f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1227f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1228f2f3bb8fSRobert Mustacchi 		break;
1229f2f3bb8fSRobert Mustacchi 	case MAC_PROP_EN_40GFDX_CAP:
1230f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1231f2f3bb8fSRobert Mustacchi 		mac_prop_info_set_default_uint8(prh,
1232f2f3bb8fSRobert Mustacchi 		    (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1233f2f3bb8fSRobert Mustacchi 		break;
1234f2f3bb8fSRobert Mustacchi 	case MAC_PROP_PRIVATE:
1235f2f3bb8fSRobert Mustacchi 		i40e_m_propinfo_private(i40e, pr_name, prh);
1236f2f3bb8fSRobert Mustacchi 		break;
1237f2f3bb8fSRobert Mustacchi 	default:
1238f2f3bb8fSRobert Mustacchi 		break;
1239f2f3bb8fSRobert Mustacchi 	}
1240f2f3bb8fSRobert Mustacchi 
1241f2f3bb8fSRobert Mustacchi 	mutex_exit(&i40e->i40e_general_lock);
1242f2f3bb8fSRobert Mustacchi }
1243f2f3bb8fSRobert Mustacchi 
1244f2f3bb8fSRobert Mustacchi #define	I40E_M_CALLBACK_FLAGS \
1245f2f3bb8fSRobert Mustacchi 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1246f2f3bb8fSRobert Mustacchi 
1247f2f3bb8fSRobert Mustacchi static mac_callbacks_t i40e_m_callbacks = {
1248f2f3bb8fSRobert Mustacchi 	I40E_M_CALLBACK_FLAGS,
1249f2f3bb8fSRobert Mustacchi 	i40e_m_stat,
1250f2f3bb8fSRobert Mustacchi 	i40e_m_start,
1251f2f3bb8fSRobert Mustacchi 	i40e_m_stop,
1252f2f3bb8fSRobert Mustacchi 	i40e_m_promisc,
1253f2f3bb8fSRobert Mustacchi 	i40e_m_multicast,
1254f2f3bb8fSRobert Mustacchi 	NULL,
1255f2f3bb8fSRobert Mustacchi 	NULL,
1256f2f3bb8fSRobert Mustacchi 	NULL,
1257f2f3bb8fSRobert Mustacchi 	i40e_m_ioctl,
1258f2f3bb8fSRobert Mustacchi 	i40e_m_getcapab,
1259f2f3bb8fSRobert Mustacchi 	NULL,
1260f2f3bb8fSRobert Mustacchi 	NULL,
1261f2f3bb8fSRobert Mustacchi 	i40e_m_setprop,
1262f2f3bb8fSRobert Mustacchi 	i40e_m_getprop,
1263f2f3bb8fSRobert Mustacchi 	i40e_m_propinfo
1264f2f3bb8fSRobert Mustacchi };
1265f2f3bb8fSRobert Mustacchi 
1266f2f3bb8fSRobert Mustacchi boolean_t
i40e_register_mac(i40e_t * i40e)1267f2f3bb8fSRobert Mustacchi i40e_register_mac(i40e_t *i40e)
1268f2f3bb8fSRobert Mustacchi {
1269f2f3bb8fSRobert Mustacchi 	struct i40e_hw *hw = &i40e->i40e_hw_space;
1270f2f3bb8fSRobert Mustacchi 	int status;
1271f2f3bb8fSRobert Mustacchi 	mac_register_t *mac = mac_alloc(MAC_VERSION);
1272f2f3bb8fSRobert Mustacchi 
1273f2f3bb8fSRobert Mustacchi 	if (mac == NULL)
1274f2f3bb8fSRobert Mustacchi 		return (B_FALSE);
1275f2f3bb8fSRobert Mustacchi 
1276f2f3bb8fSRobert Mustacchi 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1277f2f3bb8fSRobert Mustacchi 	mac->m_driver = i40e;
1278f2f3bb8fSRobert Mustacchi 	mac->m_dip = i40e->i40e_dip;
1279f2f3bb8fSRobert Mustacchi 	mac->m_src_addr = hw->mac.addr;
1280f2f3bb8fSRobert Mustacchi 	mac->m_callbacks = &i40e_m_callbacks;
1281f2f3bb8fSRobert Mustacchi 	mac->m_min_sdu = 0;
1282f2f3bb8fSRobert Mustacchi 	mac->m_max_sdu = i40e->i40e_sdu;
1283f2f3bb8fSRobert Mustacchi 	mac->m_margin = VLAN_TAGSZ;
1284f2f3bb8fSRobert Mustacchi 	mac->m_priv_props = i40e_priv_props;
1285f2f3bb8fSRobert Mustacchi 	mac->m_v12n = MAC_VIRT_LEVEL1;
1286f2f3bb8fSRobert Mustacchi 
1287f2f3bb8fSRobert Mustacchi 	status = mac_register(mac, &i40e->i40e_mac_hdl);
1288f2f3bb8fSRobert Mustacchi 	if (status != 0)
1289f2f3bb8fSRobert Mustacchi 		i40e_error(i40e, "mac_register() returned %d", status);
1290f2f3bb8fSRobert Mustacchi 	mac_free(mac);
1291f2f3bb8fSRobert Mustacchi 
1292f2f3bb8fSRobert Mustacchi 	return (status == 0);
1293f2f3bb8fSRobert Mustacchi }
1294