1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell Octeon EP (EndPoint) Ethernet Driver
3  *
4  * Copyright (C) 2020 Marvell.
5  *
6  */
7 
8 #include <linux/pci.h>
9 #include <linux/netdevice.h>
10 #include <linux/ethtool.h>
11 
12 #include "octep_config.h"
13 #include "octep_main.h"
14 #include "octep_ctrl_net.h"
15 
16 static const char octep_gstrings_global_stats[][ETH_GSTRING_LEN] = {
17 	"rx_packets",
18 	"tx_packets",
19 	"rx_bytes",
20 	"tx_bytes",
21 	"rx_alloc_errors",
22 	"tx_busy_errors",
23 	"rx_dropped",
24 	"tx_dropped",
25 	"tx_hw_pkts",
26 	"tx_hw_octs",
27 	"tx_hw_bcast",
28 	"tx_hw_mcast",
29 	"tx_hw_underflow",
30 	"tx_hw_control",
31 	"tx_less_than_64",
32 	"tx_equal_64",
33 	"tx_equal_65_to_127",
34 	"tx_equal_128_to_255",
35 	"tx_equal_256_to_511",
36 	"tx_equal_512_to_1023",
37 	"tx_equal_1024_to_1518",
38 	"tx_greater_than_1518",
39 	"rx_hw_pkts",
40 	"rx_hw_bytes",
41 	"rx_hw_bcast",
42 	"rx_hw_mcast",
43 	"rx_pause_pkts",
44 	"rx_pause_bytes",
45 	"rx_dropped_pkts_fifo_full",
46 	"rx_dropped_bytes_fifo_full",
47 	"rx_err_pkts",
48 };
49 
50 #define OCTEP_GLOBAL_STATS_CNT (sizeof(octep_gstrings_global_stats) / ETH_GSTRING_LEN)
51 
52 static const char octep_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
53 	"tx_packets_posted[Q-%u]",
54 	"tx_packets_completed[Q-%u]",
55 	"tx_bytes[Q-%u]",
56 	"tx_busy[Q-%u]",
57 };
58 
59 #define OCTEP_TX_Q_STATS_CNT (sizeof(octep_gstrings_tx_q_stats) / ETH_GSTRING_LEN)
60 
61 static const char octep_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
62 	"rx_packets[Q-%u]",
63 	"rx_bytes[Q-%u]",
64 	"rx_alloc_errors[Q-%u]",
65 };
66 
67 #define OCTEP_RX_Q_STATS_CNT (sizeof(octep_gstrings_rx_q_stats) / ETH_GSTRING_LEN)
68 
octep_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)69 static void octep_get_drvinfo(struct net_device *netdev,
70 			      struct ethtool_drvinfo *info)
71 {
72 	struct octep_device *oct = netdev_priv(netdev);
73 
74 	strscpy(info->driver, OCTEP_DRV_NAME, sizeof(info->driver));
75 	strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));
76 }
77 
octep_get_strings(struct net_device * netdev,u32 stringset,u8 * data)78 static void octep_get_strings(struct net_device *netdev,
79 			      u32 stringset, u8 *data)
80 {
81 	struct octep_device *oct = netdev_priv(netdev);
82 	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
83 	char *strings = (char *)data;
84 	int i, j;
85 
86 	switch (stringset) {
87 	case ETH_SS_STATS:
88 		for (i = 0; i < OCTEP_GLOBAL_STATS_CNT; i++) {
89 			snprintf(strings, ETH_GSTRING_LEN,
90 				 octep_gstrings_global_stats[i]);
91 			strings += ETH_GSTRING_LEN;
92 		}
93 
94 		for (i = 0; i < num_queues; i++) {
95 			for (j = 0; j < OCTEP_TX_Q_STATS_CNT; j++) {
96 				snprintf(strings, ETH_GSTRING_LEN,
97 					 octep_gstrings_tx_q_stats[j], i);
98 				strings += ETH_GSTRING_LEN;
99 			}
100 		}
101 
102 		for (i = 0; i < num_queues; i++) {
103 			for (j = 0; j < OCTEP_RX_Q_STATS_CNT; j++) {
104 				snprintf(strings, ETH_GSTRING_LEN,
105 					 octep_gstrings_rx_q_stats[j], i);
106 				strings += ETH_GSTRING_LEN;
107 			}
108 		}
109 		break;
110 	default:
111 		break;
112 	}
113 }
114 
octep_get_sset_count(struct net_device * netdev,int sset)115 static int octep_get_sset_count(struct net_device *netdev, int sset)
116 {
117 	struct octep_device *oct = netdev_priv(netdev);
118 	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
119 
120 	switch (sset) {
121 	case ETH_SS_STATS:
122 		return OCTEP_GLOBAL_STATS_CNT + (num_queues *
123 		       (OCTEP_TX_Q_STATS_CNT + OCTEP_RX_Q_STATS_CNT));
124 		break;
125 	default:
126 		return -EOPNOTSUPP;
127 	}
128 }
129 
130 static void
octep_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)131 octep_get_ethtool_stats(struct net_device *netdev,
132 			struct ethtool_stats *stats, u64 *data)
133 {
134 	struct octep_device *oct = netdev_priv(netdev);
135 	struct octep_iface_tx_stats *iface_tx_stats;
136 	struct octep_iface_rx_stats *iface_rx_stats;
137 	u64 rx_packets, rx_bytes;
138 	u64 tx_packets, tx_bytes;
139 	u64 rx_alloc_errors, tx_busy_errors;
140 	int q, i;
141 
142 	rx_packets = 0;
143 	rx_bytes = 0;
144 	tx_packets = 0;
145 	tx_bytes = 0;
146 	rx_alloc_errors = 0;
147 	tx_busy_errors = 0;
148 	tx_packets = 0;
149 	tx_bytes = 0;
150 	rx_packets = 0;
151 	rx_bytes = 0;
152 
153 	iface_tx_stats = &oct->iface_tx_stats;
154 	iface_rx_stats = &oct->iface_rx_stats;
155 	octep_ctrl_net_get_if_stats(oct,
156 				    OCTEP_CTRL_NET_INVALID_VFID,
157 				    iface_rx_stats,
158 				    iface_tx_stats);
159 
160 	for (q = 0; q < oct->num_oqs; q++) {
161 		struct octep_iq *iq = oct->iq[q];
162 		struct octep_oq *oq = oct->oq[q];
163 
164 		tx_packets += iq->stats.instr_completed;
165 		tx_bytes += iq->stats.bytes_sent;
166 		tx_busy_errors += iq->stats.tx_busy;
167 
168 		rx_packets += oq->stats.packets;
169 		rx_bytes += oq->stats.bytes;
170 		rx_alloc_errors += oq->stats.alloc_failures;
171 	}
172 	i = 0;
173 	data[i++] = rx_packets;
174 	data[i++] = tx_packets;
175 	data[i++] = rx_bytes;
176 	data[i++] = tx_bytes;
177 	data[i++] = rx_alloc_errors;
178 	data[i++] = tx_busy_errors;
179 	data[i++] = iface_rx_stats->dropped_pkts_fifo_full +
180 		    iface_rx_stats->err_pkts;
181 	data[i++] = iface_tx_stats->xscol +
182 		    iface_tx_stats->xsdef;
183 	data[i++] = iface_tx_stats->pkts;
184 	data[i++] = iface_tx_stats->octs;
185 	data[i++] = iface_tx_stats->bcst;
186 	data[i++] = iface_tx_stats->mcst;
187 	data[i++] = iface_tx_stats->undflw;
188 	data[i++] = iface_tx_stats->ctl;
189 	data[i++] = iface_tx_stats->hist_lt64;
190 	data[i++] = iface_tx_stats->hist_eq64;
191 	data[i++] = iface_tx_stats->hist_65to127;
192 	data[i++] = iface_tx_stats->hist_128to255;
193 	data[i++] = iface_tx_stats->hist_256to511;
194 	data[i++] = iface_tx_stats->hist_512to1023;
195 	data[i++] = iface_tx_stats->hist_1024to1518;
196 	data[i++] = iface_tx_stats->hist_gt1518;
197 	data[i++] = iface_rx_stats->pkts;
198 	data[i++] = iface_rx_stats->octets;
199 	data[i++] = iface_rx_stats->mcast_pkts;
200 	data[i++] = iface_rx_stats->bcast_pkts;
201 	data[i++] = iface_rx_stats->pause_pkts;
202 	data[i++] = iface_rx_stats->pause_octets;
203 	data[i++] = iface_rx_stats->dropped_pkts_fifo_full;
204 	data[i++] = iface_rx_stats->dropped_octets_fifo_full;
205 	data[i++] = iface_rx_stats->err_pkts;
206 
207 	/* Per Tx Queue stats */
208 	for (q = 0; q < oct->num_iqs; q++) {
209 		struct octep_iq *iq = oct->iq[q];
210 
211 		data[i++] = iq->stats.instr_posted;
212 		data[i++] = iq->stats.instr_completed;
213 		data[i++] = iq->stats.bytes_sent;
214 		data[i++] = iq->stats.tx_busy;
215 	}
216 
217 	/* Per Rx Queue stats */
218 	for (q = 0; q < oct->num_oqs; q++) {
219 		struct octep_oq *oq = oct->oq[q];
220 
221 		data[i++] = oq->stats.packets;
222 		data[i++] = oq->stats.bytes;
223 		data[i++] = oq->stats.alloc_failures;
224 	}
225 }
226 
227 #define OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(octep_speeds, ksettings, name) \
228 { \
229 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_T)) \
230 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \
231 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_R)) \
232 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \
233 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_CR)) \
234 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \
235 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_KR)) \
236 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \
237 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_LR)) \
238 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \
239 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_SR)) \
240 		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \
241 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_CR)) \
242 		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \
243 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_KR)) \
244 		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \
245 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_SR)) \
246 		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \
247 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_CR4)) \
248 		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \
249 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_KR4)) \
250 		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \
251 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_LR4)) \
252 		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \
253 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_SR4)) \
254 		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \
255 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR2)) \
256 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \
257 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR2)) \
258 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \
259 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR2)) \
260 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \
261 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR)) \
262 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \
263 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR)) \
264 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \
265 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_LR)) \
266 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \
267 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR)) \
268 		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \
269 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_CR4)) \
270 		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \
271 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_KR4)) \
272 		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \
273 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_LR4)) \
274 		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \
275 	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_SR4)) \
276 		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \
277 }
278 
octep_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)279 static int octep_get_link_ksettings(struct net_device *netdev,
280 				    struct ethtool_link_ksettings *cmd)
281 {
282 	struct octep_device *oct = netdev_priv(netdev);
283 	struct octep_iface_link_info *link_info;
284 	u32 advertised_modes, supported_modes;
285 
286 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
287 	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
288 
289 	link_info = &oct->link_info;
290 	octep_ctrl_net_get_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID, link_info);
291 
292 	advertised_modes = oct->link_info.advertised_modes;
293 	supported_modes = oct->link_info.supported_modes;
294 
295 	OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);
296 	OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);
297 
298 	if (link_info->autoneg) {
299 		if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED)
300 			ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
301 		if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_ADVERTISED) {
302 			ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
303 			cmd->base.autoneg = AUTONEG_ENABLE;
304 		} else {
305 			cmd->base.autoneg = AUTONEG_DISABLE;
306 		}
307 	} else {
308 		cmd->base.autoneg = AUTONEG_DISABLE;
309 	}
310 
311 	if (link_info->pause) {
312 		if (link_info->pause & OCTEP_LINK_MODE_PAUSE_SUPPORTED)
313 			ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
314 		if (link_info->pause & OCTEP_LINK_MODE_PAUSE_ADVERTISED)
315 			ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
316 	}
317 
318 	cmd->base.port = PORT_FIBRE;
319 	ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
320 	ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
321 
322 	if (netif_carrier_ok(netdev)) {
323 		cmd->base.speed = link_info->speed;
324 		cmd->base.duplex = DUPLEX_FULL;
325 	} else {
326 		cmd->base.speed = SPEED_UNKNOWN;
327 		cmd->base.duplex = DUPLEX_UNKNOWN;
328 	}
329 	return 0;
330 }
331 
octep_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)332 static int octep_set_link_ksettings(struct net_device *netdev,
333 				    const struct ethtool_link_ksettings *cmd)
334 {
335 	struct octep_device *oct = netdev_priv(netdev);
336 	struct octep_iface_link_info link_info_new;
337 	struct octep_iface_link_info *link_info;
338 	u64 advertised = 0;
339 	u8 autoneg = 0;
340 	int err;
341 
342 	link_info = &oct->link_info;
343 	memcpy(&link_info_new, link_info, sizeof(struct octep_iface_link_info));
344 
345 	/* Only Full duplex is supported;
346 	 * Assume full duplex when duplex is unknown.
347 	 */
348 	if (cmd->base.duplex != DUPLEX_FULL &&
349 	    cmd->base.duplex != DUPLEX_UNKNOWN)
350 		return -EOPNOTSUPP;
351 
352 	if (cmd->base.autoneg == AUTONEG_ENABLE) {
353 		if (!(link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED))
354 			return -EOPNOTSUPP;
355 		autoneg = 1;
356 	}
357 
358 	if (!bitmap_subset(cmd->link_modes.advertising,
359 			   cmd->link_modes.supported,
360 			   __ETHTOOL_LINK_MODE_MASK_NBITS))
361 		return -EINVAL;
362 
363 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
364 						  10000baseT_Full))
365 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_T);
366 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
367 						  10000baseR_FEC))
368 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_R);
369 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
370 						  10000baseCR_Full))
371 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_CR);
372 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
373 						  10000baseKR_Full))
374 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_KR);
375 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
376 						  10000baseLR_Full))
377 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_LR);
378 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
379 						  10000baseSR_Full))
380 		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_SR);
381 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
382 						  25000baseCR_Full))
383 		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_CR);
384 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
385 						  25000baseKR_Full))
386 		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_KR);
387 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
388 						  25000baseSR_Full))
389 		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_SR);
390 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
391 						  40000baseCR4_Full))
392 		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_CR4);
393 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
394 						  40000baseKR4_Full))
395 		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_KR4);
396 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
397 						  40000baseLR4_Full))
398 		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_LR4);
399 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
400 						  40000baseSR4_Full))
401 		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_SR4);
402 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
403 						  50000baseCR2_Full))
404 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR2);
405 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
406 						  50000baseKR2_Full))
407 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR2);
408 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
409 						  50000baseSR2_Full))
410 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR2);
411 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
412 						  50000baseCR_Full))
413 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR);
414 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
415 						  50000baseKR_Full))
416 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR);
417 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
418 						  50000baseLR_ER_FR_Full))
419 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_LR);
420 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
421 						  50000baseSR_Full))
422 		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR);
423 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
424 						  100000baseCR4_Full))
425 		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_CR4);
426 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
427 						  100000baseKR4_Full))
428 		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_KR4);
429 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
430 						  100000baseLR4_ER4_Full))
431 		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_LR4);
432 	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
433 						  100000baseSR4_Full))
434 		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_SR4);
435 
436 	if (advertised == link_info->advertised_modes &&
437 	    cmd->base.speed == link_info->speed &&
438 	    cmd->base.autoneg == link_info->autoneg)
439 		return 0;
440 
441 	link_info_new.advertised_modes = advertised;
442 	link_info_new.speed = cmd->base.speed;
443 	link_info_new.autoneg = autoneg;
444 
445 	err = octep_ctrl_net_set_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID,
446 					   &link_info_new, true);
447 	if (err)
448 		return err;
449 
450 	memcpy(link_info, &link_info_new, sizeof(struct octep_iface_link_info));
451 	return 0;
452 }
453 
454 static const struct ethtool_ops octep_ethtool_ops = {
455 	.get_drvinfo = octep_get_drvinfo,
456 	.get_link = ethtool_op_get_link,
457 	.get_strings = octep_get_strings,
458 	.get_sset_count = octep_get_sset_count,
459 	.get_ethtool_stats = octep_get_ethtool_stats,
460 	.get_link_ksettings = octep_get_link_ksettings,
461 	.set_link_ksettings = octep_set_link_ksettings,
462 };
463 
octep_set_ethtool_ops(struct net_device * netdev)464 void octep_set_ethtool_ops(struct net_device *netdev)
465 {
466 	netdev->ethtool_ops = &octep_ethtool_ops;
467 }
468