Skip to content

Commit 5064896

Browse files
shinas-marvelldavem330
authored andcommitted
octeon_ep_vf: add ethtool support
Add support for the following ethtool commands: ethtool -i|--driver devname ethtool devname ethtool -S|--statistics devname Signed-off-by: Shinas Rasheed <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 77cef1e commit 5064896

File tree

5 files changed

+312
-2
lines changed

5 files changed

+312
-2
lines changed

drivers/net/ethernet/marvell/octeon_ep_vf/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
obj-$(CONFIG_OCTEON_EP_VF) += octeon_ep_vf.o
77

88
octeon_ep_vf-y := octep_vf_main.o octep_vf_cn9k.o octep_vf_cnxk.o \
9-
octep_vf_tx.o octep_vf_rx.o octep_vf_mbox.o
9+
octep_vf_tx.o octep_vf_rx.o octep_vf_mbox.o \
10+
octep_vf_ethtool.o
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
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+
15+
static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = {
16+
"rx_packets",
17+
"tx_packets",
18+
"rx_bytes",
19+
"tx_bytes",
20+
"rx_alloc_errors",
21+
"tx_busy_errors",
22+
"rx_dropped",
23+
"tx_dropped",
24+
"tx_hw_pkts",
25+
"tx_hw_octs",
26+
"tx_hw_bcast",
27+
"tx_hw_mcast",
28+
"rx_hw_pkts",
29+
"rx_hw_bytes",
30+
"rx_hw_bcast",
31+
"rx_hw_mcast",
32+
"rx_dropped_pkts_fifo_full",
33+
"rx_dropped_bytes_fifo_full",
34+
"rx_err_pkts",
35+
};
36+
37+
#define OCTEP_VF_GLOBAL_STATS_CNT (sizeof(octep_vf_gstrings_global_stats) / ETH_GSTRING_LEN)
38+
39+
static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
40+
"tx_packets_posted[Q-%u]",
41+
"tx_packets_completed[Q-%u]",
42+
"tx_bytes[Q-%u]",
43+
"tx_busy[Q-%u]",
44+
};
45+
46+
#define OCTEP_VF_TX_Q_STATS_CNT (sizeof(octep_vf_gstrings_tx_q_stats) / ETH_GSTRING_LEN)
47+
48+
static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
49+
"rx_packets[Q-%u]",
50+
"rx_bytes[Q-%u]",
51+
"rx_alloc_errors[Q-%u]",
52+
};
53+
54+
#define OCTEP_VF_RX_Q_STATS_CNT (sizeof(octep_vf_gstrings_rx_q_stats) / ETH_GSTRING_LEN)
55+
56+
static void octep_vf_get_drvinfo(struct net_device *netdev,
57+
struct ethtool_drvinfo *info)
58+
{
59+
struct octep_vf_device *oct = netdev_priv(netdev);
60+
61+
strscpy(info->driver, OCTEP_VF_DRV_NAME, sizeof(info->driver));
62+
strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));
63+
}
64+
65+
static void octep_vf_get_strings(struct net_device *netdev,
66+
u32 stringset, u8 *data)
67+
{
68+
struct octep_vf_device *oct = netdev_priv(netdev);
69+
u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
70+
char *strings = (char *)data;
71+
int i, j;
72+
73+
switch (stringset) {
74+
case ETH_SS_STATS:
75+
for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++) {
76+
snprintf(strings, ETH_GSTRING_LEN,
77+
octep_vf_gstrings_global_stats[i]);
78+
strings += ETH_GSTRING_LEN;
79+
}
80+
81+
for (i = 0; i < num_queues; i++) {
82+
for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) {
83+
snprintf(strings, ETH_GSTRING_LEN,
84+
octep_vf_gstrings_tx_q_stats[j], i);
85+
strings += ETH_GSTRING_LEN;
86+
}
87+
}
88+
89+
for (i = 0; i < num_queues; i++) {
90+
for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) {
91+
snprintf(strings, ETH_GSTRING_LEN,
92+
octep_vf_gstrings_rx_q_stats[j], i);
93+
strings += ETH_GSTRING_LEN;
94+
}
95+
}
96+
break;
97+
default:
98+
break;
99+
}
100+
}
101+
102+
static int octep_vf_get_sset_count(struct net_device *netdev, int sset)
103+
{
104+
struct octep_vf_device *oct = netdev_priv(netdev);
105+
u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
106+
107+
switch (sset) {
108+
case ETH_SS_STATS:
109+
return OCTEP_VF_GLOBAL_STATS_CNT + (num_queues *
110+
(OCTEP_VF_TX_Q_STATS_CNT + OCTEP_VF_RX_Q_STATS_CNT));
111+
break;
112+
default:
113+
return -EOPNOTSUPP;
114+
}
115+
}
116+
117+
static void octep_vf_get_ethtool_stats(struct net_device *netdev,
118+
struct ethtool_stats *stats, u64 *data)
119+
{
120+
struct octep_vf_device *oct = netdev_priv(netdev);
121+
struct octep_vf_iface_tx_stats *iface_tx_stats;
122+
struct octep_vf_iface_rx_stats *iface_rx_stats;
123+
u64 rx_alloc_errors, tx_busy_errors;
124+
u64 rx_packets, rx_bytes;
125+
u64 tx_packets, tx_bytes;
126+
int q, i;
127+
128+
rx_packets = 0;
129+
rx_bytes = 0;
130+
tx_packets = 0;
131+
tx_bytes = 0;
132+
rx_alloc_errors = 0;
133+
tx_busy_errors = 0;
134+
tx_packets = 0;
135+
tx_bytes = 0;
136+
rx_packets = 0;
137+
rx_bytes = 0;
138+
139+
octep_vf_get_if_stats(oct);
140+
iface_tx_stats = &oct->iface_tx_stats;
141+
iface_rx_stats = &oct->iface_rx_stats;
142+
143+
for (q = 0; q < oct->num_oqs; q++) {
144+
struct octep_vf_iq *iq = oct->iq[q];
145+
struct octep_vf_oq *oq = oct->oq[q];
146+
147+
tx_packets += iq->stats.instr_completed;
148+
tx_bytes += iq->stats.bytes_sent;
149+
tx_busy_errors += iq->stats.tx_busy;
150+
151+
rx_packets += oq->stats.packets;
152+
rx_bytes += oq->stats.bytes;
153+
rx_alloc_errors += oq->stats.alloc_failures;
154+
}
155+
i = 0;
156+
data[i++] = rx_packets;
157+
data[i++] = tx_packets;
158+
data[i++] = rx_bytes;
159+
data[i++] = tx_bytes;
160+
data[i++] = rx_alloc_errors;
161+
data[i++] = tx_busy_errors;
162+
data[i++] = iface_rx_stats->dropped_pkts_fifo_full +
163+
iface_rx_stats->err_pkts;
164+
data[i++] = iface_tx_stats->dropped;
165+
data[i++] = iface_tx_stats->pkts;
166+
data[i++] = iface_tx_stats->octs;
167+
data[i++] = iface_tx_stats->bcst;
168+
data[i++] = iface_tx_stats->mcst;
169+
data[i++] = iface_rx_stats->pkts;
170+
data[i++] = iface_rx_stats->octets;
171+
data[i++] = iface_rx_stats->mcast_pkts;
172+
data[i++] = iface_rx_stats->bcast_pkts;
173+
data[i++] = iface_rx_stats->dropped_pkts_fifo_full;
174+
data[i++] = iface_rx_stats->dropped_octets_fifo_full;
175+
data[i++] = iface_rx_stats->err_pkts;
176+
177+
/* Per Tx Queue stats */
178+
for (q = 0; q < oct->num_iqs; q++) {
179+
struct octep_vf_iq *iq = oct->iq[q];
180+
181+
data[i++] = iq->stats.instr_posted;
182+
data[i++] = iq->stats.instr_completed;
183+
data[i++] = iq->stats.bytes_sent;
184+
data[i++] = iq->stats.tx_busy;
185+
}
186+
187+
/* Per Rx Queue stats */
188+
for (q = 0; q < oct->num_oqs; q++) {
189+
struct octep_vf_oq *oq = oct->oq[q];
190+
191+
data[i++] = oq->stats.packets;
192+
data[i++] = oq->stats.bytes;
193+
data[i++] = oq->stats.alloc_failures;
194+
}
195+
}
196+
197+
#define OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(octep_vf_speeds, ksettings, name) \
198+
{ \
199+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_T)) \
200+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \
201+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_R)) \
202+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \
203+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_CR)) \
204+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \
205+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_KR)) \
206+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \
207+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_LR)) \
208+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \
209+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_SR)) \
210+
ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \
211+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_CR)) \
212+
ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \
213+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_KR)) \
214+
ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \
215+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_SR)) \
216+
ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \
217+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_CR4)) \
218+
ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \
219+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_KR4)) \
220+
ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \
221+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_LR4)) \
222+
ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \
223+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_SR4)) \
224+
ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \
225+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR2)) \
226+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \
227+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR2)) \
228+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \
229+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR2)) \
230+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \
231+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR)) \
232+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \
233+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR)) \
234+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \
235+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_LR)) \
236+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \
237+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR)) \
238+
ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \
239+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_CR4)) \
240+
ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \
241+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_KR4)) \
242+
ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \
243+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_LR4)) \
244+
ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \
245+
if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_SR4)) \
246+
ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \
247+
}
248+
249+
static int octep_vf_get_link_ksettings(struct net_device *netdev,
250+
struct ethtool_link_ksettings *cmd)
251+
{
252+
struct octep_vf_device *oct = netdev_priv(netdev);
253+
struct octep_vf_iface_link_info *link_info;
254+
u32 advertised_modes, supported_modes;
255+
256+
ethtool_link_ksettings_zero_link_mode(cmd, supported);
257+
ethtool_link_ksettings_zero_link_mode(cmd, advertising);
258+
259+
octep_vf_get_link_info(oct);
260+
261+
advertised_modes = oct->link_info.advertised_modes;
262+
supported_modes = oct->link_info.supported_modes;
263+
link_info = &oct->link_info;
264+
265+
OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);
266+
OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);
267+
268+
if (link_info->autoneg) {
269+
if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED)
270+
ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
271+
if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED) {
272+
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
273+
cmd->base.autoneg = AUTONEG_ENABLE;
274+
} else {
275+
cmd->base.autoneg = AUTONEG_DISABLE;
276+
}
277+
} else {
278+
cmd->base.autoneg = AUTONEG_DISABLE;
279+
}
280+
281+
cmd->base.port = PORT_FIBRE;
282+
ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
283+
ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
284+
285+
if (netif_carrier_ok(netdev)) {
286+
cmd->base.speed = link_info->speed;
287+
cmd->base.duplex = DUPLEX_FULL;
288+
} else {
289+
cmd->base.speed = SPEED_UNKNOWN;
290+
cmd->base.duplex = DUPLEX_UNKNOWN;
291+
}
292+
return 0;
293+
}
294+
295+
static const struct ethtool_ops octep_vf_ethtool_ops = {
296+
.get_drvinfo = octep_vf_get_drvinfo,
297+
.get_link = ethtool_op_get_link,
298+
.get_strings = octep_vf_get_strings,
299+
.get_sset_count = octep_vf_get_sset_count,
300+
.get_ethtool_stats = octep_vf_get_ethtool_stats,
301+
.get_link_ksettings = octep_vf_get_link_ksettings,
302+
};
303+
304+
void octep_vf_set_ethtool_ops(struct net_device *netdev)
305+
{
306+
netdev->ethtool_ops = &octep_vf_ethtool_ops;
307+
}

drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ static int octep_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
10811081
INIT_WORK(&octep_vf_dev->tx_timeout_task, octep_vf_tx_timeout_task);
10821082

10831083
netdev->netdev_ops = &octep_vf_netdev_ops;
1084+
octep_vf_set_ethtool_ops(netdev);
10841085
netif_carrier_off(netdev);
10851086

10861087
if (octep_vf_setup_mbox(octep_vf_dev)) {

drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ void octep_vf_device_setup_cn93(struct octep_vf_device *oct);
331331
void octep_vf_device_setup_cnxk(struct octep_vf_device *oct);
332332
int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget);
333333
int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget);
334+
void octep_vf_set_ethtool_ops(struct net_device *netdev);
334335
int octep_vf_get_link_info(struct octep_vf_device *oct);
335336
int octep_vf_get_if_stats(struct octep_vf_device *oct);
336337
void octep_vf_mbox_work(struct work_struct *work);

drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct,
114114
{
115115
struct octep_vf_mbox *mbox = oct->mbox;
116116
u64 reg_val = 0ull;
117-
int count;
117+
int count = 0;
118118

119119
if (!mbox)
120120
return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;

0 commit comments

Comments
 (0)