1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell Octeon EP (EndPoint) Ethernet Driver
4 * Copyright (C) 2020 Marvell.
9 #include <linux/netdevice.h>
10 #include <linux/ethtool.h>
12 #include "octep_config.h"
13 #include "octep_main.h"
14 #include "octep_ctrl_net.h"
16 static const char octep_gstrings_global_stats[][ETH_GSTRING_LEN] = {
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",
45 "rx_dropped_pkts_fifo_full",
46 "rx_dropped_bytes_fifo_full",
50 #define OCTEP_GLOBAL_STATS_CNT (sizeof(octep_gstrings_global_stats) / ETH_GSTRING_LEN)
52 static const char octep_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
53 "tx_packets_posted[Q-%u]",
54 "tx_packets_completed[Q-%u]",
59 #define OCTEP_TX_Q_STATS_CNT (sizeof(octep_gstrings_tx_q_stats) / ETH_GSTRING_LEN)
61 static const char octep_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
64 "rx_alloc_errors[Q-%u]",
67 #define OCTEP_RX_Q_STATS_CNT (sizeof(octep_gstrings_rx_q_stats) / ETH_GSTRING_LEN)
69 static void octep_get_drvinfo(struct net_device *netdev,
70 struct ethtool_drvinfo *info)
72 struct octep_device *oct = netdev_priv(netdev);
74 strscpy(info->driver, OCTEP_DRV_NAME, sizeof(info->driver));
75 strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));
78 static void octep_get_strings(struct net_device *netdev,
79 u32 stringset, u8 *data)
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;
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;
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;
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;
115 static int octep_get_sset_count(struct net_device *netdev, int sset)
117 struct octep_device *oct = netdev_priv(netdev);
118 u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
122 return OCTEP_GLOBAL_STATS_CNT + (num_queues *
123 (OCTEP_TX_Q_STATS_CNT + OCTEP_RX_Q_STATS_CNT));
131 octep_get_ethtool_stats(struct net_device *netdev,
132 struct ethtool_stats *stats, u64 *data)
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;
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,
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];
164 tx_packets += iq->stats.instr_completed;
165 tx_bytes += iq->stats.bytes_sent;
166 tx_busy_errors += iq->stats.tx_busy;
168 rx_packets += oq->stats.packets;
169 rx_bytes += oq->stats.bytes;
170 rx_alloc_errors += oq->stats.alloc_failures;
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;
207 /* Per Tx Queue stats */
208 for (q = 0; q < oct->num_iqs; q++) {
209 struct octep_iq *iq = oct->iq[q];
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;
217 /* Per Rx Queue stats */
218 for (q = 0; q < oct->num_oqs; q++) {
219 struct octep_oq *oq = oct->oq[q];
221 data[i++] = oq->stats.packets;
222 data[i++] = oq->stats.bytes;
223 data[i++] = oq->stats.alloc_failures;
227 #define OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(octep_speeds, ksettings, name) \
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); \
279 static int octep_get_link_ksettings(struct net_device *netdev,
280 struct ethtool_link_ksettings *cmd)
282 struct octep_device *oct = netdev_priv(netdev);
283 struct octep_iface_link_info *link_info;
284 u32 advertised_modes, supported_modes;
286 ethtool_link_ksettings_zero_link_mode(cmd, supported);
287 ethtool_link_ksettings_zero_link_mode(cmd, advertising);
289 link_info = &oct->link_info;
290 octep_ctrl_net_get_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID, link_info);
292 advertised_modes = oct->link_info.advertised_modes;
293 supported_modes = oct->link_info.supported_modes;
295 OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);
296 OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);
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;
305 cmd->base.autoneg = AUTONEG_DISABLE;
308 cmd->base.autoneg = AUTONEG_DISABLE;
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);
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);
322 if (netif_carrier_ok(netdev)) {
323 cmd->base.speed = link_info->speed;
324 cmd->base.duplex = DUPLEX_FULL;
326 cmd->base.speed = SPEED_UNKNOWN;
327 cmd->base.duplex = DUPLEX_UNKNOWN;
332 static int octep_set_link_ksettings(struct net_device *netdev,
333 const struct ethtool_link_ksettings *cmd)
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;
342 link_info = &oct->link_info;
343 memcpy(&link_info_new, link_info, sizeof(struct octep_iface_link_info));
345 /* Only Full duplex is supported;
346 * Assume full duplex when duplex is unknown.
348 if (cmd->base.duplex != DUPLEX_FULL &&
349 cmd->base.duplex != DUPLEX_UNKNOWN)
352 if (cmd->base.autoneg == AUTONEG_ENABLE) {
353 if (!(link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED))
358 if (!bitmap_subset(cmd->link_modes.advertising,
359 cmd->link_modes.supported,
360 __ETHTOOL_LINK_MODE_MASK_NBITS))
363 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
365 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_T);
366 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
368 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_R);
369 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
371 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_CR);
372 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
374 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_KR);
375 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
377 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_LR);
378 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
380 advertised |= BIT(OCTEP_LINK_MODE_10GBASE_SR);
381 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
383 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_CR);
384 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
386 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_KR);
387 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
389 advertised |= BIT(OCTEP_LINK_MODE_25GBASE_SR);
390 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
392 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_CR4);
393 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
395 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_KR4);
396 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
398 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_LR4);
399 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
401 advertised |= BIT(OCTEP_LINK_MODE_40GBASE_SR4);
402 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
404 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR2);
405 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
407 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR2);
408 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
410 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR2);
411 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
413 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR);
414 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
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,
422 advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR);
423 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
425 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_CR4);
426 if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
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,
434 advertised |= BIT(OCTEP_LINK_MODE_100GBASE_SR4);
436 if (advertised == link_info->advertised_modes &&
437 cmd->base.speed == link_info->speed &&
438 cmd->base.autoneg == link_info->autoneg)
441 link_info_new.advertised_modes = advertised;
442 link_info_new.speed = cmd->base.speed;
443 link_info_new.autoneg = autoneg;
445 err = octep_ctrl_net_set_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID,
446 &link_info_new, true);
450 memcpy(link_info, &link_info_new, sizeof(struct octep_iface_link_info));
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,
464 void octep_set_ethtool_ops(struct net_device *netdev)
466 netdev->ethtool_ops = &octep_ethtool_ops;