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