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}