Linux Audio

Check our new training course

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}