1ab69bde6SJohannes Berg /*
2ab69bde6SJohannes Berg * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net>
3ab69bde6SJohannes Berg *
4ab69bde6SJohannes Berg * This file is free software: you may copy, redistribute and/or modify it
5ab69bde6SJohannes Berg * under the terms of the GNU General Public License as published by the
6ab69bde6SJohannes Berg * Free Software Foundation, either version 2 of the License, or (at your
7ab69bde6SJohannes Berg * option) any later version.
8ab69bde6SJohannes Berg *
9ab69bde6SJohannes Berg * This file is distributed in the hope that it will be useful, but
10ab69bde6SJohannes Berg * WITHOUT ANY WARRANTY; without even the implied warranty of
11ab69bde6SJohannes Berg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12ab69bde6SJohannes Berg * General Public License for more details.
13ab69bde6SJohannes Berg *
14ab69bde6SJohannes Berg * You should have received a copy of the GNU General Public License
15ab69bde6SJohannes Berg * along with this program. If not, see <http://www.gnu.org/licenses/>.
16ab69bde6SJohannes Berg *
17ab69bde6SJohannes Berg * This file incorporates work covered by the following copyright and
18ab69bde6SJohannes Berg * permission notice:
19ab69bde6SJohannes Berg *
20ab69bde6SJohannes Berg * Copyright (c) 2012 Qualcomm Atheros, Inc.
21ab69bde6SJohannes Berg *
22ab69bde6SJohannes Berg * Permission to use, copy, modify, and/or distribute this software for any
23ab69bde6SJohannes Berg * purpose with or without fee is hereby granted, provided that the above
24ab69bde6SJohannes Berg * copyright notice and this permission notice appear in all copies.
25ab69bde6SJohannes Berg *
26ab69bde6SJohannes Berg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27ab69bde6SJohannes Berg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28ab69bde6SJohannes Berg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29ab69bde6SJohannes Berg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30ab69bde6SJohannes Berg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31ab69bde6SJohannes Berg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32ab69bde6SJohannes Berg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33ab69bde6SJohannes Berg */
34ab69bde6SJohannes Berg
35ab69bde6SJohannes Berg #include <linux/pci.h>
36ab69bde6SJohannes Berg #include <linux/ip.h>
37ab69bde6SJohannes Berg #include <linux/tcp.h>
38ab69bde6SJohannes Berg #include <linux/netdevice.h>
39ab69bde6SJohannes Berg #include <linux/etherdevice.h>
40ab69bde6SJohannes Berg #include <linux/ethtool.h>
41ab69bde6SJohannes Berg #include <linux/mdio.h>
42ab69bde6SJohannes Berg #include <linux/interrupt.h>
43ab69bde6SJohannes Berg #include <asm/byteorder.h>
44ab69bde6SJohannes Berg
45ab69bde6SJohannes Berg #include "alx.h"
46ab69bde6SJohannes Berg #include "reg.h"
47ab69bde6SJohannes Berg #include "hw.h"
48ab69bde6SJohannes Berg
49b7e6ce18SSabrina Dubroca /* The order of these strings must match the order of the fields in
50b7e6ce18SSabrina Dubroca * struct alx_hw_stats
51b7e6ce18SSabrina Dubroca * See hw.h
52b7e6ce18SSabrina Dubroca */
53b7e6ce18SSabrina Dubroca static const char alx_gstrings_stats[][ETH_GSTRING_LEN] = {
54b7e6ce18SSabrina Dubroca "rx_packets",
55b7e6ce18SSabrina Dubroca "rx_bcast_packets",
56b7e6ce18SSabrina Dubroca "rx_mcast_packets",
57b7e6ce18SSabrina Dubroca "rx_pause_packets",
58b7e6ce18SSabrina Dubroca "rx_ctrl_packets",
59b7e6ce18SSabrina Dubroca "rx_fcs_errors",
60b7e6ce18SSabrina Dubroca "rx_length_errors",
61b7e6ce18SSabrina Dubroca "rx_bytes",
62b7e6ce18SSabrina Dubroca "rx_runt_packets",
63b7e6ce18SSabrina Dubroca "rx_fragments",
64b7e6ce18SSabrina Dubroca "rx_64B_or_less_packets",
65b7e6ce18SSabrina Dubroca "rx_65B_to_127B_packets",
66b7e6ce18SSabrina Dubroca "rx_128B_to_255B_packets",
67b7e6ce18SSabrina Dubroca "rx_256B_to_511B_packets",
68b7e6ce18SSabrina Dubroca "rx_512B_to_1023B_packets",
69b7e6ce18SSabrina Dubroca "rx_1024B_to_1518B_packets",
70b7e6ce18SSabrina Dubroca "rx_1519B_to_mtu_packets",
71b7e6ce18SSabrina Dubroca "rx_oversize_packets",
72b7e6ce18SSabrina Dubroca "rx_rxf_ov_drop_packets",
73b7e6ce18SSabrina Dubroca "rx_rrd_ov_drop_packets",
74b7e6ce18SSabrina Dubroca "rx_align_errors",
75b7e6ce18SSabrina Dubroca "rx_bcast_bytes",
76b7e6ce18SSabrina Dubroca "rx_mcast_bytes",
77b7e6ce18SSabrina Dubroca "rx_address_errors",
78b7e6ce18SSabrina Dubroca "tx_packets",
79b7e6ce18SSabrina Dubroca "tx_bcast_packets",
80b7e6ce18SSabrina Dubroca "tx_mcast_packets",
81b7e6ce18SSabrina Dubroca "tx_pause_packets",
82b7e6ce18SSabrina Dubroca "tx_exc_defer_packets",
83b7e6ce18SSabrina Dubroca "tx_ctrl_packets",
84b7e6ce18SSabrina Dubroca "tx_defer_packets",
85b7e6ce18SSabrina Dubroca "tx_bytes",
86b7e6ce18SSabrina Dubroca "tx_64B_or_less_packets",
87b7e6ce18SSabrina Dubroca "tx_65B_to_127B_packets",
88b7e6ce18SSabrina Dubroca "tx_128B_to_255B_packets",
89b7e6ce18SSabrina Dubroca "tx_256B_to_511B_packets",
90b7e6ce18SSabrina Dubroca "tx_512B_to_1023B_packets",
91b7e6ce18SSabrina Dubroca "tx_1024B_to_1518B_packets",
92b7e6ce18SSabrina Dubroca "tx_1519B_to_mtu_packets",
93b7e6ce18SSabrina Dubroca "tx_single_collision",
94b7e6ce18SSabrina Dubroca "tx_multiple_collisions",
95b7e6ce18SSabrina Dubroca "tx_late_collision",
96b7e6ce18SSabrina Dubroca "tx_abort_collision",
97b7e6ce18SSabrina Dubroca "tx_underrun",
98b7e6ce18SSabrina Dubroca "tx_trd_eop",
99b7e6ce18SSabrina Dubroca "tx_length_errors",
100b7e6ce18SSabrina Dubroca "tx_trunc_packets",
101b7e6ce18SSabrina Dubroca "tx_bcast_bytes",
102b7e6ce18SSabrina Dubroca "tx_mcast_bytes",
103b7e6ce18SSabrina Dubroca "tx_update",
104b7e6ce18SSabrina Dubroca };
105b7e6ce18SSabrina Dubroca
106b7e6ce18SSabrina Dubroca #define ALX_NUM_STATS ARRAY_SIZE(alx_gstrings_stats)
107b7e6ce18SSabrina Dubroca
108b7e6ce18SSabrina Dubroca
alx_get_supported_speeds(struct alx_hw * hw)1097ec56894SJohannes Berg static u32 alx_get_supported_speeds(struct alx_hw *hw)
1107ec56894SJohannes Berg {
1117ec56894SJohannes Berg u32 supported = SUPPORTED_10baseT_Half |
1127ec56894SJohannes Berg SUPPORTED_10baseT_Full |
1137ec56894SJohannes Berg SUPPORTED_100baseT_Half |
1147ec56894SJohannes Berg SUPPORTED_100baseT_Full;
1157ec56894SJohannes Berg
1167ec56894SJohannes Berg if (alx_hw_giga(hw))
1177ec56894SJohannes Berg supported |= SUPPORTED_1000baseT_Full;
1187ec56894SJohannes Berg
1197ec56894SJohannes Berg BUILD_BUG_ON(SUPPORTED_10baseT_Half != ADVERTISED_10baseT_Half);
1207ec56894SJohannes Berg BUILD_BUG_ON(SUPPORTED_10baseT_Full != ADVERTISED_10baseT_Full);
1217ec56894SJohannes Berg BUILD_BUG_ON(SUPPORTED_100baseT_Half != ADVERTISED_100baseT_Half);
1227ec56894SJohannes Berg BUILD_BUG_ON(SUPPORTED_100baseT_Full != ADVERTISED_100baseT_Full);
1237ec56894SJohannes Berg BUILD_BUG_ON(SUPPORTED_1000baseT_Full != ADVERTISED_1000baseT_Full);
1247ec56894SJohannes Berg
1257ec56894SJohannes Berg return supported;
1267ec56894SJohannes Berg }
127ab69bde6SJohannes Berg
alx_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)12836a4e690SPhilippe Reynes static int alx_get_link_ksettings(struct net_device *netdev,
12936a4e690SPhilippe Reynes struct ethtool_link_ksettings *cmd)
130ab69bde6SJohannes Berg {
131ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
132ab69bde6SJohannes Berg struct alx_hw *hw = &alx->hw;
13336a4e690SPhilippe Reynes u32 supported, advertising;
134ab69bde6SJohannes Berg
13536a4e690SPhilippe Reynes supported = SUPPORTED_Autoneg |
136ab69bde6SJohannes Berg SUPPORTED_TP |
1377ec56894SJohannes Berg SUPPORTED_Pause |
1387ec56894SJohannes Berg SUPPORTED_Asym_Pause;
139ab69bde6SJohannes Berg if (alx_hw_giga(hw))
14036a4e690SPhilippe Reynes supported |= SUPPORTED_1000baseT_Full;
14136a4e690SPhilippe Reynes supported |= alx_get_supported_speeds(hw);
142ab69bde6SJohannes Berg
14336a4e690SPhilippe Reynes advertising = ADVERTISED_TP;
144ab69bde6SJohannes Berg if (hw->adv_cfg & ADVERTISED_Autoneg)
14536a4e690SPhilippe Reynes advertising |= hw->adv_cfg;
146ab69bde6SJohannes Berg
14736a4e690SPhilippe Reynes cmd->base.port = PORT_TP;
14836a4e690SPhilippe Reynes cmd->base.phy_address = 0;
1497ec56894SJohannes Berg
150ab69bde6SJohannes Berg if (hw->adv_cfg & ADVERTISED_Autoneg)
15136a4e690SPhilippe Reynes cmd->base.autoneg = AUTONEG_ENABLE;
152ab69bde6SJohannes Berg else
15336a4e690SPhilippe Reynes cmd->base.autoneg = AUTONEG_DISABLE;
154ab69bde6SJohannes Berg
155ab69bde6SJohannes Berg if (hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg) {
156ab69bde6SJohannes Berg if (hw->flowctrl & ALX_FC_RX) {
15736a4e690SPhilippe Reynes advertising |= ADVERTISED_Pause;
158ab69bde6SJohannes Berg
159ab69bde6SJohannes Berg if (!(hw->flowctrl & ALX_FC_TX))
16036a4e690SPhilippe Reynes advertising |= ADVERTISED_Asym_Pause;
161ab69bde6SJohannes Berg } else if (hw->flowctrl & ALX_FC_TX) {
16236a4e690SPhilippe Reynes advertising |= ADVERTISED_Asym_Pause;
163ab69bde6SJohannes Berg }
164ab69bde6SJohannes Berg }
165ab69bde6SJohannes Berg
1664a5fe57eSJohannes Berg mutex_lock(&alx->mtx);
16736a4e690SPhilippe Reynes cmd->base.speed = hw->link_speed;
16836a4e690SPhilippe Reynes cmd->base.duplex = hw->duplex;
1694a5fe57eSJohannes Berg mutex_unlock(&alx->mtx);
17036a4e690SPhilippe Reynes
17136a4e690SPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
17236a4e690SPhilippe Reynes supported);
17336a4e690SPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
17436a4e690SPhilippe Reynes advertising);
175ab69bde6SJohannes Berg
176ab69bde6SJohannes Berg return 0;
177ab69bde6SJohannes Berg }
178ab69bde6SJohannes Berg
alx_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)17936a4e690SPhilippe Reynes static int alx_set_link_ksettings(struct net_device *netdev,
18036a4e690SPhilippe Reynes const struct ethtool_link_ksettings *cmd)
181ab69bde6SJohannes Berg {
182ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
183ab69bde6SJohannes Berg struct alx_hw *hw = &alx->hw;
184ab69bde6SJohannes Berg u32 adv_cfg;
18536a4e690SPhilippe Reynes u32 advertising;
1864a5fe57eSJohannes Berg int ret;
187ab69bde6SJohannes Berg
18836a4e690SPhilippe Reynes ethtool_convert_link_mode_to_legacy_u32(&advertising,
18936a4e690SPhilippe Reynes cmd->link_modes.advertising);
19036a4e690SPhilippe Reynes
19136a4e690SPhilippe Reynes if (cmd->base.autoneg == AUTONEG_ENABLE) {
19236a4e690SPhilippe Reynes if (advertising & ~alx_get_supported_speeds(hw))
193ab69bde6SJohannes Berg return -EINVAL;
19436a4e690SPhilippe Reynes adv_cfg = advertising | ADVERTISED_Autoneg;
195ab69bde6SJohannes Berg } else {
19636a4e690SPhilippe Reynes adv_cfg = alx_speed_to_ethadv(cmd->base.speed,
19736a4e690SPhilippe Reynes cmd->base.duplex);
198ab69bde6SJohannes Berg
199a5b87cc9SJohannes Berg if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full)
200ab69bde6SJohannes Berg return -EINVAL;
201ab69bde6SJohannes Berg }
202ab69bde6SJohannes Berg
203ab69bde6SJohannes Berg hw->adv_cfg = adv_cfg;
2044a5fe57eSJohannes Berg
2054a5fe57eSJohannes Berg mutex_lock(&alx->mtx);
2064a5fe57eSJohannes Berg ret = alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl);
2074a5fe57eSJohannes Berg mutex_unlock(&alx->mtx);
2084a5fe57eSJohannes Berg
2094a5fe57eSJohannes Berg return ret;
210ab69bde6SJohannes Berg }
211ab69bde6SJohannes Berg
alx_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)212ab69bde6SJohannes Berg static void alx_get_pauseparam(struct net_device *netdev,
213ab69bde6SJohannes Berg struct ethtool_pauseparam *pause)
214ab69bde6SJohannes Berg {
215ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
216ab69bde6SJohannes Berg struct alx_hw *hw = &alx->hw;
217ab69bde6SJohannes Berg
2184a5fe57eSJohannes Berg mutex_lock(&alx->mtx);
2197ec56894SJohannes Berg pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG &&
2207ec56894SJohannes Berg hw->adv_cfg & ADVERTISED_Autoneg);
2217ec56894SJohannes Berg pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX);
2227ec56894SJohannes Berg pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX);
2234a5fe57eSJohannes Berg mutex_unlock(&alx->mtx);
224ab69bde6SJohannes Berg }
225ab69bde6SJohannes Berg
226ab69bde6SJohannes Berg
alx_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)227ab69bde6SJohannes Berg static int alx_set_pauseparam(struct net_device *netdev,
228ab69bde6SJohannes Berg struct ethtool_pauseparam *pause)
229ab69bde6SJohannes Berg {
230ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
231ab69bde6SJohannes Berg struct alx_hw *hw = &alx->hw;
232ab69bde6SJohannes Berg int err = 0;
233ab69bde6SJohannes Berg bool reconfig_phy = false;
234ab69bde6SJohannes Berg u8 fc = 0;
235ab69bde6SJohannes Berg
236ab69bde6SJohannes Berg if (pause->tx_pause)
237ab69bde6SJohannes Berg fc |= ALX_FC_TX;
238ab69bde6SJohannes Berg if (pause->rx_pause)
239ab69bde6SJohannes Berg fc |= ALX_FC_RX;
240ab69bde6SJohannes Berg if (pause->autoneg)
241ab69bde6SJohannes Berg fc |= ALX_FC_ANEG;
242ab69bde6SJohannes Berg
2434a5fe57eSJohannes Berg mutex_lock(&alx->mtx);
244ab69bde6SJohannes Berg
245ab69bde6SJohannes Berg /* restart auto-neg for auto-mode */
246ab69bde6SJohannes Berg if (hw->adv_cfg & ADVERTISED_Autoneg) {
247ab69bde6SJohannes Berg if (!((fc ^ hw->flowctrl) & ALX_FC_ANEG))
248ab69bde6SJohannes Berg reconfig_phy = true;
249ab69bde6SJohannes Berg if (fc & hw->flowctrl & ALX_FC_ANEG &&
250ab69bde6SJohannes Berg (fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX))
251ab69bde6SJohannes Berg reconfig_phy = true;
252ab69bde6SJohannes Berg }
253ab69bde6SJohannes Berg
254ab69bde6SJohannes Berg if (reconfig_phy) {
255ab69bde6SJohannes Berg err = alx_setup_speed_duplex(hw, hw->adv_cfg, fc);
2562d1c5f29SPu Lehui if (err) {
2572d1c5f29SPu Lehui mutex_unlock(&alx->mtx);
258ab69bde6SJohannes Berg return err;
259ab69bde6SJohannes Berg }
2602d1c5f29SPu Lehui }
261ab69bde6SJohannes Berg
262ab69bde6SJohannes Berg /* flow control on mac */
263ab69bde6SJohannes Berg if ((fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX))
264ab69bde6SJohannes Berg alx_cfg_mac_flowcontrol(hw, fc);
265ab69bde6SJohannes Berg
266ab69bde6SJohannes Berg hw->flowctrl = fc;
2674a5fe57eSJohannes Berg mutex_unlock(&alx->mtx);
268ab69bde6SJohannes Berg
269ab69bde6SJohannes Berg return 0;
270ab69bde6SJohannes Berg }
271ab69bde6SJohannes Berg
alx_get_msglevel(struct net_device * netdev)272ab69bde6SJohannes Berg static u32 alx_get_msglevel(struct net_device *netdev)
273ab69bde6SJohannes Berg {
274ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
275ab69bde6SJohannes Berg
276ab69bde6SJohannes Berg return alx->msg_enable;
277ab69bde6SJohannes Berg }
278ab69bde6SJohannes Berg
alx_set_msglevel(struct net_device * netdev,u32 data)279ab69bde6SJohannes Berg static void alx_set_msglevel(struct net_device *netdev, u32 data)
280ab69bde6SJohannes Berg {
281ab69bde6SJohannes Berg struct alx_priv *alx = netdev_priv(netdev);
282ab69bde6SJohannes Berg
283ab69bde6SJohannes Berg alx->msg_enable = data;
284ab69bde6SJohannes Berg }
285ab69bde6SJohannes Berg
alx_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * estats,u64 * data)286b7e6ce18SSabrina Dubroca static void alx_get_ethtool_stats(struct net_device *netdev,
287b7e6ce18SSabrina Dubroca struct ethtool_stats *estats, u64 *data)
288b7e6ce18SSabrina Dubroca {
289b7e6ce18SSabrina Dubroca struct alx_priv *alx = netdev_priv(netdev);
290b7e6ce18SSabrina Dubroca struct alx_hw *hw = &alx->hw;
291b7e6ce18SSabrina Dubroca
292b7e6ce18SSabrina Dubroca spin_lock(&alx->stats_lock);
293b7e6ce18SSabrina Dubroca
294b7e6ce18SSabrina Dubroca alx_update_hw_stats(hw);
295*3a198c95SGONG, Ruiqi BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64));
296*3a198c95SGONG, Ruiqi memcpy(data, &hw->stats, sizeof(hw->stats));
297b7e6ce18SSabrina Dubroca
298b7e6ce18SSabrina Dubroca spin_unlock(&alx->stats_lock);
299b7e6ce18SSabrina Dubroca }
300b7e6ce18SSabrina Dubroca
alx_get_strings(struct net_device * netdev,u32 stringset,u8 * buf)301b7e6ce18SSabrina Dubroca static void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
302b7e6ce18SSabrina Dubroca {
303b7e6ce18SSabrina Dubroca switch (stringset) {
304b7e6ce18SSabrina Dubroca case ETH_SS_STATS:
305b7e6ce18SSabrina Dubroca memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats));
306b7e6ce18SSabrina Dubroca break;
307b7e6ce18SSabrina Dubroca default:
308b7e6ce18SSabrina Dubroca WARN_ON(1);
309b7e6ce18SSabrina Dubroca break;
310b7e6ce18SSabrina Dubroca }
311b7e6ce18SSabrina Dubroca }
312b7e6ce18SSabrina Dubroca
alx_get_sset_count(struct net_device * netdev,int sset)313b7e6ce18SSabrina Dubroca static int alx_get_sset_count(struct net_device *netdev, int sset)
314b7e6ce18SSabrina Dubroca {
315b7e6ce18SSabrina Dubroca switch (sset) {
316b7e6ce18SSabrina Dubroca case ETH_SS_STATS:
317b7e6ce18SSabrina Dubroca return ALX_NUM_STATS;
318b7e6ce18SSabrina Dubroca default:
319b7e6ce18SSabrina Dubroca return -EINVAL;
320b7e6ce18SSabrina Dubroca }
321b7e6ce18SSabrina Dubroca }
322b7e6ce18SSabrina Dubroca
323ab69bde6SJohannes Berg const struct ethtool_ops alx_ethtool_ops = {
324ab69bde6SJohannes Berg .get_pauseparam = alx_get_pauseparam,
325ab69bde6SJohannes Berg .set_pauseparam = alx_set_pauseparam,
326ab69bde6SJohannes Berg .get_msglevel = alx_get_msglevel,
327ab69bde6SJohannes Berg .set_msglevel = alx_set_msglevel,
328ab69bde6SJohannes Berg .get_link = ethtool_op_get_link,
329b7e6ce18SSabrina Dubroca .get_strings = alx_get_strings,
330b7e6ce18SSabrina Dubroca .get_sset_count = alx_get_sset_count,
331b7e6ce18SSabrina Dubroca .get_ethtool_stats = alx_get_ethtool_stats,
33236a4e690SPhilippe Reynes .get_link_ksettings = alx_get_link_ksettings,
33336a4e690SPhilippe Reynes .set_link_ksettings = alx_set_link_ksettings,
334ab69bde6SJohannes Berg };
335