Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Marvell Octeon EP (EndPoint) VF 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_vf_config.h"
 13#include "octep_vf_main.h"
 14
 15static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = {
 16	"rx_alloc_errors",
 17	"tx_busy_errors",
 18	"tx_hw_pkts",
 19	"tx_hw_octs",
 20	"tx_hw_bcast",
 21	"tx_hw_mcast",
 22	"rx_hw_pkts",
 23	"rx_hw_bytes",
 24	"rx_hw_bcast",
 25	"rx_dropped_bytes_fifo_full",
 26};
 27
 28#define OCTEP_VF_GLOBAL_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_global_stats)
 29
 30static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
 31	"tx_packets_posted[Q-%u]",
 32	"tx_packets_completed[Q-%u]",
 33	"tx_bytes[Q-%u]",
 34	"tx_busy[Q-%u]",
 35};
 36
 37#define OCTEP_VF_TX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_tx_q_stats)
 38
 39static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
 40	"rx_packets[Q-%u]",
 41	"rx_bytes[Q-%u]",
 42	"rx_alloc_errors[Q-%u]",
 43};
 44
 45#define OCTEP_VF_RX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_rx_q_stats)
 46
 47static void octep_vf_get_drvinfo(struct net_device *netdev,
 48				 struct ethtool_drvinfo *info)
 49{
 50	struct octep_vf_device *oct = netdev_priv(netdev);
 51
 52	strscpy(info->driver, OCTEP_VF_DRV_NAME, sizeof(info->driver));
 53	strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));
 54}
 55
 56static void octep_vf_get_strings(struct net_device *netdev,
 57				 u32 stringset, u8 *data)
 58{
 59	struct octep_vf_device *oct = netdev_priv(netdev);
 60	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
 61	const char *str;
 62	int i, j;
 63
 64	switch (stringset) {
 65	case ETH_SS_STATS:
 66		for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++)
 67			ethtool_puts(&data, octep_vf_gstrings_global_stats[i]);
 68
 69		for (i = 0; i < num_queues; i++)
 70			for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) {
 71				str = octep_vf_gstrings_tx_q_stats[j];
 72				ethtool_sprintf(&data, str, i);
 73			}
 74
 75		for (i = 0; i < num_queues; i++)
 76			for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) {
 77				str = octep_vf_gstrings_rx_q_stats[j];
 78				ethtool_sprintf(&data, str, i);
 79			}
 80		break;
 81	default:
 82		break;
 83	}
 84}
 85
 86static int octep_vf_get_sset_count(struct net_device *netdev, int sset)
 87{
 88	struct octep_vf_device *oct = netdev_priv(netdev);
 89	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
 90
 91	switch (sset) {
 92	case ETH_SS_STATS:
 93		return OCTEP_VF_GLOBAL_STATS_CNT + (num_queues *
 94		       (OCTEP_VF_TX_Q_STATS_CNT + OCTEP_VF_RX_Q_STATS_CNT));
 95		break;
 96	default:
 97		return -EOPNOTSUPP;
 98	}
 99}
100
101static void octep_vf_get_ethtool_stats(struct net_device *netdev,
102				       struct ethtool_stats *stats, u64 *data)
103{
104	struct octep_vf_device *oct = netdev_priv(netdev);
105	struct octep_vf_iface_tx_stats *iface_tx_stats;
106	struct octep_vf_iface_rx_stats *iface_rx_stats;
107	u64 rx_alloc_errors, tx_busy_errors;
108	int q, i;
109
110	rx_alloc_errors = 0;
111	tx_busy_errors = 0;
112
113	octep_vf_get_if_stats(oct);
114	iface_tx_stats = &oct->iface_tx_stats;
115	iface_rx_stats = &oct->iface_rx_stats;
116
117	for (q = 0; q < OCTEP_VF_MAX_QUEUES; q++) {
118		tx_busy_errors += oct->stats_iq[q].tx_busy;
119		rx_alloc_errors += oct->stats_oq[q].alloc_failures;
120	}
121	i = 0;
122	data[i++] = rx_alloc_errors;
123	data[i++] = tx_busy_errors;
124	data[i++] = iface_tx_stats->pkts;
125	data[i++] = iface_tx_stats->octs;
126	data[i++] = iface_tx_stats->bcst;
127	data[i++] = iface_tx_stats->mcst;
128	data[i++] = iface_rx_stats->pkts;
129	data[i++] = iface_rx_stats->octets;
130	data[i++] = iface_rx_stats->bcast_pkts;
131	data[i++] = iface_rx_stats->dropped_octets_fifo_full;
132
133	/* Per Tx Queue stats */
134	for (q = 0; q < OCTEP_VF_MAX_QUEUES; q++) {
135		data[i++] = oct->stats_iq[q].instr_posted;
136		data[i++] = oct->stats_iq[q].instr_completed;
137		data[i++] = oct->stats_iq[q].bytes_sent;
138		data[i++] = oct->stats_iq[q].tx_busy;
139	}
140
141	/* Per Rx Queue stats */
142	for (q = 0; q < oct->num_oqs; q++) {
143		data[i++] = oct->stats_oq[q].packets;
144		data[i++] = oct->stats_oq[q].bytes;
145		data[i++] = oct->stats_oq[q].alloc_failures;
146	}
147}
148
149#define OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(octep_vf_speeds, ksettings, name) \
150{ \
151	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_T)) \
152		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \
153	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_R)) \
154		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \
155	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_CR)) \
156		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \
157	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_KR)) \
158		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \
159	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_LR)) \
160		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \
161	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_SR)) \
162		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \
163	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_CR)) \
164		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \
165	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_KR)) \
166		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \
167	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_SR)) \
168		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \
169	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_CR4)) \
170		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \
171	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_KR4)) \
172		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \
173	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_LR4)) \
174		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \
175	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_SR4)) \
176		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \
177	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR2)) \
178		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \
179	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR2)) \
180		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \
181	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR2)) \
182		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \
183	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR)) \
184		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \
185	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR)) \
186		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \
187	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_LR)) \
188		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \
189	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR)) \
190		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \
191	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_CR4)) \
192		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \
193	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_KR4)) \
194		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \
195	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_LR4)) \
196		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \
197	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_SR4)) \
198		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \
199}
200
201static int octep_vf_get_link_ksettings(struct net_device *netdev,
202				       struct ethtool_link_ksettings *cmd)
203{
204	struct octep_vf_device *oct = netdev_priv(netdev);
205	struct octep_vf_iface_link_info *link_info;
206	u32 advertised_modes, supported_modes;
207
208	ethtool_link_ksettings_zero_link_mode(cmd, supported);
209	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
210
211	octep_vf_get_link_info(oct);
212
213	advertised_modes = oct->link_info.advertised_modes;
214	supported_modes = oct->link_info.supported_modes;
215	link_info = &oct->link_info;
216
217	OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);
218	OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);
219
220	if (link_info->autoneg) {
221		if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED)
222			ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
223		if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED) {
224			ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
225			cmd->base.autoneg = AUTONEG_ENABLE;
226		} else {
227			cmd->base.autoneg = AUTONEG_DISABLE;
228		}
229	} else {
230		cmd->base.autoneg = AUTONEG_DISABLE;
231	}
232
233	cmd->base.port = PORT_FIBRE;
234	ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
235	ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
236
237	if (netif_carrier_ok(netdev)) {
238		cmd->base.speed = link_info->speed;
239		cmd->base.duplex = DUPLEX_FULL;
240	} else {
241		cmd->base.speed = SPEED_UNKNOWN;
242		cmd->base.duplex = DUPLEX_UNKNOWN;
243	}
244	return 0;
245}
246
247static const struct ethtool_ops octep_vf_ethtool_ops = {
248	.get_drvinfo = octep_vf_get_drvinfo,
249	.get_link = ethtool_op_get_link,
250	.get_strings = octep_vf_get_strings,
251	.get_sset_count = octep_vf_get_sset_count,
252	.get_ethtool_stats = octep_vf_get_ethtool_stats,
253	.get_link_ksettings = octep_vf_get_link_ksettings,
254};
255
256void octep_vf_set_ethtool_ops(struct net_device *netdev)
257{
258	netdev->ethtool_ops = &octep_vf_ethtool_ops;
259}