Loading...
Note: File does not exist in v4.6.
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
16static 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 ARRAY_SIZE(octep_gstrings_global_stats)
51
52static 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 ARRAY_SIZE(octep_gstrings_tx_q_stats)
60
61static 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 ARRAY_SIZE(octep_gstrings_rx_q_stats)
68
69static 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
78static 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 const char *str;
84 int i, j;
85
86 switch (stringset) {
87 case ETH_SS_STATS:
88 for (i = 0; i < OCTEP_GLOBAL_STATS_CNT; i++)
89 ethtool_puts(&data, octep_gstrings_global_stats[i]);
90
91 for (i = 0; i < num_queues; i++)
92 for (j = 0; j < OCTEP_TX_Q_STATS_CNT; j++) {
93 str = octep_gstrings_tx_q_stats[j];
94 ethtool_sprintf(&data, str, i);
95 }
96
97 for (i = 0; i < num_queues; i++)
98 for (j = 0; j < OCTEP_RX_Q_STATS_CNT; j++) {
99 str = octep_gstrings_rx_q_stats[j];
100 ethtool_sprintf(&data, str, i);
101 }
102 break;
103 default:
104 break;
105 }
106}
107
108static int octep_get_sset_count(struct net_device *netdev, int sset)
109{
110 struct octep_device *oct = netdev_priv(netdev);
111 u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
112
113 switch (sset) {
114 case ETH_SS_STATS:
115 return OCTEP_GLOBAL_STATS_CNT + (num_queues *
116 (OCTEP_TX_Q_STATS_CNT + OCTEP_RX_Q_STATS_CNT));
117 break;
118 default:
119 return -EOPNOTSUPP;
120 }
121}
122
123static void
124octep_get_ethtool_stats(struct net_device *netdev,
125 struct ethtool_stats *stats, u64 *data)
126{
127 struct octep_device *oct = netdev_priv(netdev);
128 struct octep_iface_tx_stats *iface_tx_stats;
129 struct octep_iface_rx_stats *iface_rx_stats;
130 u64 rx_packets, rx_bytes;
131 u64 tx_packets, tx_bytes;
132 u64 rx_alloc_errors, tx_busy_errors;
133 int q, i;
134
135 rx_packets = 0;
136 rx_bytes = 0;
137 tx_packets = 0;
138 tx_bytes = 0;
139 rx_alloc_errors = 0;
140 tx_busy_errors = 0;
141 tx_packets = 0;
142 tx_bytes = 0;
143 rx_packets = 0;
144 rx_bytes = 0;
145
146 iface_tx_stats = &oct->iface_tx_stats;
147 iface_rx_stats = &oct->iface_rx_stats;
148 octep_ctrl_net_get_if_stats(oct,
149 OCTEP_CTRL_NET_INVALID_VFID,
150 iface_rx_stats,
151 iface_tx_stats);
152
153 for (q = 0; q < OCTEP_MAX_QUEUES; q++) {
154 tx_packets += oct->stats_iq[q].instr_completed;
155 tx_bytes += oct->stats_iq[q].bytes_sent;
156 tx_busy_errors += oct->stats_iq[q].tx_busy;
157
158 rx_packets += oct->stats_oq[q].packets;
159 rx_bytes += oct->stats_oq[q].bytes;
160 rx_alloc_errors += oct->stats_oq[q].alloc_failures;
161 }
162 i = 0;
163 data[i++] = rx_packets;
164 data[i++] = tx_packets;
165 data[i++] = rx_bytes;
166 data[i++] = tx_bytes;
167 data[i++] = rx_alloc_errors;
168 data[i++] = tx_busy_errors;
169 data[i++] = iface_rx_stats->dropped_pkts_fifo_full +
170 iface_rx_stats->err_pkts;
171 data[i++] = iface_tx_stats->xscol +
172 iface_tx_stats->xsdef;
173 data[i++] = iface_tx_stats->pkts;
174 data[i++] = iface_tx_stats->octs;
175 data[i++] = iface_tx_stats->bcst;
176 data[i++] = iface_tx_stats->mcst;
177 data[i++] = iface_tx_stats->undflw;
178 data[i++] = iface_tx_stats->ctl;
179 data[i++] = iface_tx_stats->hist_lt64;
180 data[i++] = iface_tx_stats->hist_eq64;
181 data[i++] = iface_tx_stats->hist_65to127;
182 data[i++] = iface_tx_stats->hist_128to255;
183 data[i++] = iface_tx_stats->hist_256to511;
184 data[i++] = iface_tx_stats->hist_512to1023;
185 data[i++] = iface_tx_stats->hist_1024to1518;
186 data[i++] = iface_tx_stats->hist_gt1518;
187 data[i++] = iface_rx_stats->pkts;
188 data[i++] = iface_rx_stats->octets;
189 data[i++] = iface_rx_stats->mcast_pkts;
190 data[i++] = iface_rx_stats->bcast_pkts;
191 data[i++] = iface_rx_stats->pause_pkts;
192 data[i++] = iface_rx_stats->pause_octets;
193 data[i++] = iface_rx_stats->dropped_pkts_fifo_full;
194 data[i++] = iface_rx_stats->dropped_octets_fifo_full;
195 data[i++] = iface_rx_stats->err_pkts;
196
197 /* Per Tx Queue stats */
198 for (q = 0; q < OCTEP_MAX_QUEUES; q++) {
199 data[i++] = oct->stats_iq[q].instr_posted;
200 data[i++] = oct->stats_iq[q].instr_completed;
201 data[i++] = oct->stats_iq[q].bytes_sent;
202 data[i++] = oct->stats_iq[q].tx_busy;
203 }
204
205 /* Per Rx Queue stats */
206 for (q = 0; q < OCTEP_MAX_QUEUES; q++) {
207 data[i++] = oct->stats_oq[q].packets;
208 data[i++] = oct->stats_oq[q].bytes;
209 data[i++] = oct->stats_oq[q].alloc_failures;
210 }
211}
212
213#define OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(octep_speeds, ksettings, name) \
214{ \
215 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_T)) \
216 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \
217 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_R)) \
218 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \
219 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_CR)) \
220 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \
221 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_KR)) \
222 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \
223 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_LR)) \
224 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \
225 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_SR)) \
226 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \
227 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_CR)) \
228 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \
229 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_KR)) \
230 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \
231 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_SR)) \
232 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \
233 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_CR4)) \
234 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \
235 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_KR4)) \
236 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \
237 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_LR4)) \
238 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \
239 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_SR4)) \
240 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \
241 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR2)) \
242 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \
243 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR2)) \
244 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \
245 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR2)) \
246 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \
247 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR)) \
248 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \
249 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR)) \
250 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \
251 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_LR)) \
252 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \
253 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR)) \
254 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \
255 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_CR4)) \
256 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \
257 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_KR4)) \
258 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \
259 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_LR4)) \
260 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \
261 if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_SR4)) \
262 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \
263}
264
265static int octep_get_link_ksettings(struct net_device *netdev,
266 struct ethtool_link_ksettings *cmd)
267{
268 struct octep_device *oct = netdev_priv(netdev);
269 struct octep_iface_link_info *link_info;
270 u32 advertised_modes, supported_modes;
271
272 ethtool_link_ksettings_zero_link_mode(cmd, supported);
273 ethtool_link_ksettings_zero_link_mode(cmd, advertising);
274
275 link_info = &oct->link_info;
276 octep_ctrl_net_get_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID, link_info);
277
278 advertised_modes = oct->link_info.advertised_modes;
279 supported_modes = oct->link_info.supported_modes;
280
281 OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);
282 OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);
283
284 if (link_info->autoneg) {
285 if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED)
286 ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
287 if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_ADVERTISED) {
288 ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
289 cmd->base.autoneg = AUTONEG_ENABLE;
290 } else {
291 cmd->base.autoneg = AUTONEG_DISABLE;
292 }
293 } else {
294 cmd->base.autoneg = AUTONEG_DISABLE;
295 }
296
297 if (link_info->pause) {
298 if (link_info->pause & OCTEP_LINK_MODE_PAUSE_SUPPORTED)
299 ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
300 if (link_info->pause & OCTEP_LINK_MODE_PAUSE_ADVERTISED)
301 ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
302 }
303
304 cmd->base.port = PORT_FIBRE;
305 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
306 ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
307
308 if (netif_carrier_ok(netdev)) {
309 cmd->base.speed = link_info->speed;
310 cmd->base.duplex = DUPLEX_FULL;
311 } else {
312 cmd->base.speed = SPEED_UNKNOWN;
313 cmd->base.duplex = DUPLEX_UNKNOWN;
314 }
315 return 0;
316}
317
318static int octep_set_link_ksettings(struct net_device *netdev,
319 const struct ethtool_link_ksettings *cmd)
320{
321 struct octep_device *oct = netdev_priv(netdev);
322 struct octep_iface_link_info link_info_new;
323 struct octep_iface_link_info *link_info;
324 u64 advertised = 0;
325 u8 autoneg = 0;
326 int err;
327
328 link_info = &oct->link_info;
329 memcpy(&link_info_new, link_info, sizeof(struct octep_iface_link_info));
330
331 /* Only Full duplex is supported;
332 * Assume full duplex when duplex is unknown.
333 */
334 if (cmd->base.duplex != DUPLEX_FULL &&
335 cmd->base.duplex != DUPLEX_UNKNOWN)
336 return -EOPNOTSUPP;
337
338 if (cmd->base.autoneg == AUTONEG_ENABLE) {
339 if (!(link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED))
340 return -EOPNOTSUPP;
341 autoneg = 1;
342 }
343
344 if (!bitmap_subset(cmd->link_modes.advertising,
345 cmd->link_modes.supported,
346 __ETHTOOL_LINK_MODE_MASK_NBITS))
347 return -EINVAL;
348
349 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
350 10000baseT_Full))
351 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_T);
352 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
353 10000baseR_FEC))
354 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_R);
355 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
356 10000baseCR_Full))
357 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_CR);
358 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
359 10000baseKR_Full))
360 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_KR);
361 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
362 10000baseLR_Full))
363 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_LR);
364 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
365 10000baseSR_Full))
366 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_SR);
367 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
368 25000baseCR_Full))
369 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_CR);
370 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
371 25000baseKR_Full))
372 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_KR);
373 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
374 25000baseSR_Full))
375 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_SR);
376 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
377 40000baseCR4_Full))
378 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_CR4);
379 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
380 40000baseKR4_Full))
381 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_KR4);
382 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
383 40000baseLR4_Full))
384 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_LR4);
385 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
386 40000baseSR4_Full))
387 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_SR4);
388 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
389 50000baseCR2_Full))
390 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR2);
391 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
392 50000baseKR2_Full))
393 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR2);
394 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
395 50000baseSR2_Full))
396 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR2);
397 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
398 50000baseCR_Full))
399 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR);
400 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
401 50000baseKR_Full))
402 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR);
403 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
404 50000baseLR_ER_FR_Full))
405 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_LR);
406 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
407 50000baseSR_Full))
408 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR);
409 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
410 100000baseCR4_Full))
411 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_CR4);
412 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
413 100000baseKR4_Full))
414 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_KR4);
415 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
416 100000baseLR4_ER4_Full))
417 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_LR4);
418 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
419 100000baseSR4_Full))
420 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_SR4);
421
422 if (advertised == link_info->advertised_modes &&
423 cmd->base.speed == link_info->speed &&
424 cmd->base.autoneg == link_info->autoneg)
425 return 0;
426
427 link_info_new.advertised_modes = advertised;
428 link_info_new.speed = cmd->base.speed;
429 link_info_new.autoneg = autoneg;
430
431 err = octep_ctrl_net_set_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID,
432 &link_info_new, true);
433 if (err)
434 return err;
435
436 memcpy(link_info, &link_info_new, sizeof(struct octep_iface_link_info));
437 return 0;
438}
439
440static const struct ethtool_ops octep_ethtool_ops = {
441 .get_drvinfo = octep_get_drvinfo,
442 .get_link = ethtool_op_get_link,
443 .get_strings = octep_get_strings,
444 .get_sset_count = octep_get_sset_count,
445 .get_ethtool_stats = octep_get_ethtool_stats,
446 .get_link_ksettings = octep_get_link_ksettings,
447 .set_link_ksettings = octep_set_link_ksettings,
448};
449
450void octep_set_ethtool_ops(struct net_device *netdev)
451{
452 netdev->ethtool_ops = &octep_ethtool_ops;
453}