1a80d38e66ec2a6c4c2f59ea1eb4274275372406
[linux-2.6-microblaze.git] / drivers / net / ethernet / google / gve / gve_ethtool.c
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Google virtual Ethernet (gve) driver
3  *
4  * Copyright (C) 2015-2019 Google, Inc.
5  */
6
7 #include <linux/rtnetlink.h>
8 #include "gve.h"
9
10 static void gve_get_drvinfo(struct net_device *netdev,
11                             struct ethtool_drvinfo *info)
12 {
13         struct gve_priv *priv = netdev_priv(netdev);
14
15         strlcpy(info->driver, "gve", sizeof(info->driver));
16         strlcpy(info->version, gve_version_str, sizeof(info->version));
17         strlcpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info));
18 }
19
20 static void gve_set_msglevel(struct net_device *netdev, u32 value)
21 {
22         struct gve_priv *priv = netdev_priv(netdev);
23
24         priv->msg_enable = value;
25 }
26
27 static u32 gve_get_msglevel(struct net_device *netdev)
28 {
29         struct gve_priv *priv = netdev_priv(netdev);
30
31         return priv->msg_enable;
32 }
33
34 static const char gve_gstrings_main_stats[][ETH_GSTRING_LEN] = {
35         "rx_packets", "tx_packets", "rx_bytes", "tx_bytes",
36         "rx_dropped", "tx_dropped", "tx_timeouts",
37 };
38
39 #define GVE_MAIN_STATS_LEN  ARRAY_SIZE(gve_gstrings_main_stats)
40 #define NUM_GVE_TX_CNTS 5
41 #define NUM_GVE_RX_CNTS 2
42
43 static void gve_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
44 {
45         struct gve_priv *priv = netdev_priv(netdev);
46         char *s = (char *)data;
47         int i;
48
49         if (stringset != ETH_SS_STATS)
50                 return;
51
52         memcpy(s, *gve_gstrings_main_stats,
53                sizeof(gve_gstrings_main_stats));
54         s += sizeof(gve_gstrings_main_stats);
55         for (i = 0; i < priv->rx_cfg.num_queues; i++) {
56                 snprintf(s, ETH_GSTRING_LEN, "rx_desc_cnt[%u]", i);
57                 s += ETH_GSTRING_LEN;
58                 snprintf(s, ETH_GSTRING_LEN, "rx_desc_fill_cnt[%u]", i);
59                 s += ETH_GSTRING_LEN;
60         }
61         for (i = 0; i < priv->tx_cfg.num_queues; i++) {
62                 snprintf(s, ETH_GSTRING_LEN, "tx_req[%u]", i);
63                 s += ETH_GSTRING_LEN;
64                 snprintf(s, ETH_GSTRING_LEN, "tx_done[%u]", i);
65                 s += ETH_GSTRING_LEN;
66                 snprintf(s, ETH_GSTRING_LEN, "tx_wake[%u]", i);
67                 s += ETH_GSTRING_LEN;
68                 snprintf(s, ETH_GSTRING_LEN, "tx_stop[%u]", i);
69                 s += ETH_GSTRING_LEN;
70                 snprintf(s, ETH_GSTRING_LEN, "tx_event_counter[%u]", i);
71                 s += ETH_GSTRING_LEN;
72         }
73 }
74
75 static int gve_get_sset_count(struct net_device *netdev, int sset)
76 {
77         struct gve_priv *priv = netdev_priv(netdev);
78
79         switch (sset) {
80         case ETH_SS_STATS:
81                 return GVE_MAIN_STATS_LEN +
82                        (priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS) +
83                        (priv->tx_cfg.num_queues * NUM_GVE_TX_CNTS);
84         default:
85                 return -EOPNOTSUPP;
86         }
87 }
88
89 static void
90 gve_get_ethtool_stats(struct net_device *netdev,
91                       struct ethtool_stats *stats, u64 *data)
92 {
93         struct gve_priv *priv = netdev_priv(netdev);
94         u64 rx_pkts, rx_bytes, tx_pkts, tx_bytes;
95         unsigned int start;
96         int ring;
97         int i;
98
99         ASSERT_RTNL();
100
101         for (rx_pkts = 0, rx_bytes = 0, ring = 0;
102              ring < priv->rx_cfg.num_queues; ring++) {
103                 if (priv->rx) {
104                         do {
105                                 start =
106                                   u64_stats_fetch_begin(&priv->rx[ring].statss);
107                                 rx_pkts += priv->rx[ring].rpackets;
108                                 rx_bytes += priv->rx[ring].rbytes;
109                         } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
110                                                        start));
111                 }
112         }
113         for (tx_pkts = 0, tx_bytes = 0, ring = 0;
114              ring < priv->tx_cfg.num_queues; ring++) {
115                 if (priv->tx) {
116                         do {
117                                 start =
118                                   u64_stats_fetch_begin(&priv->tx[ring].statss);
119                                 tx_pkts += priv->tx[ring].pkt_done;
120                                 tx_bytes += priv->tx[ring].bytes_done;
121                         } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
122                                                        start));
123                 }
124         }
125
126         i = 0;
127         data[i++] = rx_pkts;
128         data[i++] = tx_pkts;
129         data[i++] = rx_bytes;
130         data[i++] = tx_bytes;
131         /* Skip rx_dropped and tx_dropped */
132         i += 2;
133         data[i++] = priv->tx_timeo_cnt;
134         i = GVE_MAIN_STATS_LEN;
135
136         /* walk RX rings */
137         if (priv->rx) {
138                 for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
139                         struct gve_rx_ring *rx = &priv->rx[ring];
140
141                         data[i++] = rx->cnt;
142                         data[i++] = rx->fill_cnt;
143                 }
144         } else {
145                 i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
146         }
147         /* walk TX rings */
148         if (priv->tx) {
149                 for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
150                         struct gve_tx_ring *tx = &priv->tx[ring];
151
152                         data[i++] = tx->req;
153                         data[i++] = tx->done;
154                         data[i++] = tx->wake_queue;
155                         data[i++] = tx->stop_queue;
156                         data[i++] = be32_to_cpu(gve_tx_load_event_counter(priv,
157                                                                           tx));
158                 }
159         } else {
160                 i += priv->tx_cfg.num_queues * NUM_GVE_TX_CNTS;
161         }
162 }
163
164 static void gve_get_channels(struct net_device *netdev,
165                              struct ethtool_channels *cmd)
166 {
167         struct gve_priv *priv = netdev_priv(netdev);
168
169         cmd->max_rx = priv->rx_cfg.max_queues;
170         cmd->max_tx = priv->tx_cfg.max_queues;
171         cmd->max_other = 0;
172         cmd->max_combined = 0;
173         cmd->rx_count = priv->rx_cfg.num_queues;
174         cmd->tx_count = priv->tx_cfg.num_queues;
175         cmd->other_count = 0;
176         cmd->combined_count = 0;
177 }
178
179 static int gve_set_channels(struct net_device *netdev,
180                             struct ethtool_channels *cmd)
181 {
182         struct gve_priv *priv = netdev_priv(netdev);
183         struct gve_queue_config new_tx_cfg = priv->tx_cfg;
184         struct gve_queue_config new_rx_cfg = priv->rx_cfg;
185         struct ethtool_channels old_settings;
186         int new_tx = cmd->tx_count;
187         int new_rx = cmd->rx_count;
188
189         gve_get_channels(netdev, &old_settings);
190
191         /* Changing combined is not allowed allowed */
192         if (cmd->combined_count != old_settings.combined_count)
193                 return -EINVAL;
194
195         if (!new_rx || !new_tx)
196                 return -EINVAL;
197
198         if (!netif_carrier_ok(netdev)) {
199                 priv->tx_cfg.num_queues = new_tx;
200                 priv->rx_cfg.num_queues = new_rx;
201                 return 0;
202         }
203
204         new_tx_cfg.num_queues = new_tx;
205         new_rx_cfg.num_queues = new_rx;
206
207         return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg);
208 }
209
210 static void gve_get_ringparam(struct net_device *netdev,
211                               struct ethtool_ringparam *cmd)
212 {
213         struct gve_priv *priv = netdev_priv(netdev);
214
215         cmd->rx_max_pending = priv->rx_desc_cnt;
216         cmd->tx_max_pending = priv->tx_desc_cnt;
217         cmd->rx_pending = priv->rx_desc_cnt;
218         cmd->tx_pending = priv->tx_desc_cnt;
219 }
220
221 static int gve_user_reset(struct net_device *netdev, u32 *flags)
222 {
223         struct gve_priv *priv = netdev_priv(netdev);
224
225         if (*flags == ETH_RESET_ALL) {
226                 *flags = 0;
227                 return gve_reset(priv, true);
228         }
229
230         return -EOPNOTSUPP;
231 }
232
233 static int gve_get_tunable(struct net_device *netdev,
234                            const struct ethtool_tunable *etuna, void *value)
235 {
236         struct gve_priv *priv = netdev_priv(netdev);
237
238         switch (etuna->id) {
239         case ETHTOOL_RX_COPYBREAK:
240                 *(u32 *)value = priv->rx_copybreak;
241                 return 0;
242         default:
243                 return -EOPNOTSUPP;
244         }
245 }
246
247 static int gve_set_tunable(struct net_device *netdev,
248                            const struct ethtool_tunable *etuna, const void *value)
249 {
250         struct gve_priv *priv = netdev_priv(netdev);
251         u32 len;
252
253         switch (etuna->id) {
254         case ETHTOOL_RX_COPYBREAK:
255                 len = *(u32 *)value;
256                 if (len > PAGE_SIZE / 2)
257                         return -EINVAL;
258                 priv->rx_copybreak = len;
259                 return 0;
260         default:
261                 return -EOPNOTSUPP;
262         }
263 }
264
265 const struct ethtool_ops gve_ethtool_ops = {
266         .get_drvinfo = gve_get_drvinfo,
267         .get_strings = gve_get_strings,
268         .get_sset_count = gve_get_sset_count,
269         .get_ethtool_stats = gve_get_ethtool_stats,
270         .set_msglevel = gve_set_msglevel,
271         .get_msglevel = gve_get_msglevel,
272         .set_channels = gve_set_channels,
273         .get_channels = gve_get_channels,
274         .get_link = ethtool_op_get_link,
275         .get_ringparam = gve_get_ringparam,
276         .reset = gve_user_reset,
277         .get_tunable = gve_get_tunable,
278         .set_tunable = gve_set_tunable,
279 };