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 Dubrocastatic 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
1097ec56894SJohannes Bergstatic 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
12836a4e690SPhilippe Reynesstatic 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
17936a4e690SPhilippe Reynesstatic 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);
198a5b87cc9SJohannes 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
212ab69bde6SJohannes Bergstatic 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
227ab69bde6SJohannes Bergstatic 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);
258ef0cc4b1SJohannes Berg			return err;
2592d1c5f29SPu Lehui		}
260ab69bde6SJohannes Berg	}
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
272ab69bde6SJohannes Bergstatic 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
279ab69bde6SJohannes Bergstatic 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
286b7e6ce18SSabrina Dubrocastatic 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);
295b7e6ce18SSabrina Dubroca	BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
296b7e6ce18SSabrina Dubroca		     ALX_NUM_STATS * sizeof(u64));
297b7e6ce18SSabrina Dubroca	memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
298b7e6ce18SSabrina Dubroca
299b7e6ce18SSabrina Dubroca	spin_unlock(&alx->stats_lock);
300b7e6ce18SSabrina Dubroca}
301b7e6ce18SSabrina Dubroca
302b7e6ce18SSabrina Dubrocastatic void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
303b7e6ce18SSabrina Dubroca{
304b7e6ce18SSabrina Dubroca	switch (stringset) {
305b7e6ce18SSabrina Dubroca	case ETH_SS_STATS:
306b7e6ce18SSabrina Dubroca		memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats));
307b7e6ce18SSabrina Dubroca		break;
308b7e6ce18SSabrina Dubroca	default:
309b7e6ce18SSabrina Dubroca		WARN_ON(1);
310b7e6ce18SSabrina Dubroca		break;
311b7e6ce18SSabrina Dubroca	}
312b7e6ce18SSabrina Dubroca}
313b7e6ce18SSabrina Dubroca
314b7e6ce18SSabrina Dubrocastatic int alx_get_sset_count(struct net_device *netdev, int sset)
315b7e6ce18SSabrina Dubroca{
316b7e6ce18SSabrina Dubroca	switch (sset) {
317b7e6ce18SSabrina Dubroca	case ETH_SS_STATS:
318b7e6ce18SSabrina Dubroca		return ALX_NUM_STATS;
319b7e6ce18SSabrina Dubroca	default:
320b7e6ce18SSabrina Dubroca		return -EINVAL;
321b7e6ce18SSabrina Dubroca	}
322b7e6ce18SSabrina Dubroca}
323b7e6ce18SSabrina Dubroca
324ab69bde6SJohannes Bergconst struct ethtool_ops alx_ethtool_ops = {
325ab69bde6SJohannes Berg	.get_pauseparam	= alx_get_pauseparam,
326ab69bde6SJohannes Berg	.set_pauseparam	= alx_set_pauseparam,
327ab69bde6SJohannes Berg	.get_msglevel	= alx_get_msglevel,
328ab69bde6SJohannes Berg	.set_msglevel	= alx_set_msglevel,
329ab69bde6SJohannes Berg	.get_link	= ethtool_op_get_link,
330b7e6ce18SSabrina Dubroca	.get_strings	= alx_get_strings,
331b7e6ce18SSabrina Dubroca	.get_sset_count	= alx_get_sset_count,
332b7e6ce18SSabrina Dubroca	.get_ethtool_stats	= alx_get_ethtool_stats,
33336a4e690SPhilippe Reynes	.get_link_ksettings	= alx_get_link_ksettings,
33436a4e690SPhilippe Reynes	.set_link_ksettings	= alx_set_link_ksettings,
335ab69bde6SJohannes Berg};
336