1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34#include <linux/string.h>
35
36#include "dpaa_eth.h"
37#include "mac.h"
38
39static const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = {
40 "interrupts",
41 "rx packets",
42 "tx packets",
43 "tx confirm",
44 "tx S/G",
45 "tx error",
46 "rx error",
47};
48
49static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
50
51 "rx dma error",
52 "rx frame physical error",
53 "rx frame size error",
54 "rx header error",
55
56
57 "qman cg_tdrop",
58 "qman wred",
59 "qman error cond",
60 "qman early window",
61 "qman late window",
62 "qman fq tdrop",
63 "qman fq retired",
64 "qman orp disabled",
65
66
67 "congestion time (ms)",
68 "entered congestion",
69 "congested (0/1)"
70};
71
72#define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu)
73#define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global)
74
75static int dpaa_get_link_ksettings(struct net_device *net_dev,
76 struct ethtool_link_ksettings *cmd)
77{
78 if (!net_dev->phydev) {
79 netdev_dbg(net_dev, "phy device not initialized\n");
80 return 0;
81 }
82
83 phy_ethtool_ksettings_get(net_dev->phydev, cmd);
84
85 return 0;
86}
87
88static int dpaa_set_link_ksettings(struct net_device *net_dev,
89 const struct ethtool_link_ksettings *cmd)
90{
91 int err;
92
93 if (!net_dev->phydev) {
94 netdev_err(net_dev, "phy device not initialized\n");
95 return -ENODEV;
96 }
97
98 err = phy_ethtool_ksettings_set(net_dev->phydev, cmd);
99 if (err < 0)
100 netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err);
101
102 return err;
103}
104
105static void dpaa_get_drvinfo(struct net_device *net_dev,
106 struct ethtool_drvinfo *drvinfo)
107{
108 int len;
109
110 strlcpy(drvinfo->driver, KBUILD_MODNAME,
111 sizeof(drvinfo->driver));
112 len = snprintf(drvinfo->version, sizeof(drvinfo->version),
113 "%X", 0);
114 len = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
115 "%X", 0);
116
117 if (len >= sizeof(drvinfo->fw_version)) {
118
119 netdev_notice(net_dev, "snprintf() = %d\n", len);
120 }
121 strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
122 sizeof(drvinfo->bus_info));
123}
124
125static u32 dpaa_get_msglevel(struct net_device *net_dev)
126{
127 return ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable;
128}
129
130static void dpaa_set_msglevel(struct net_device *net_dev,
131 u32 msg_enable)
132{
133 ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable = msg_enable;
134}
135
136static int dpaa_nway_reset(struct net_device *net_dev)
137{
138 int err;
139
140 if (!net_dev->phydev) {
141 netdev_err(net_dev, "phy device not initialized\n");
142 return -ENODEV;
143 }
144
145 err = 0;
146 if (net_dev->phydev->autoneg) {
147 err = phy_start_aneg(net_dev->phydev);
148 if (err < 0)
149 netdev_err(net_dev, "phy_start_aneg() = %d\n",
150 err);
151 }
152
153 return err;
154}
155
156static void dpaa_get_pauseparam(struct net_device *net_dev,
157 struct ethtool_pauseparam *epause)
158{
159 struct mac_device *mac_dev;
160 struct dpaa_priv *priv;
161
162 priv = netdev_priv(net_dev);
163 mac_dev = priv->mac_dev;
164
165 if (!net_dev->phydev) {
166 netdev_err(net_dev, "phy device not initialized\n");
167 return;
168 }
169
170 epause->autoneg = mac_dev->autoneg_pause;
171 epause->rx_pause = mac_dev->rx_pause_active;
172 epause->tx_pause = mac_dev->tx_pause_active;
173}
174
175static int dpaa_set_pauseparam(struct net_device *net_dev,
176 struct ethtool_pauseparam *epause)
177{
178 struct mac_device *mac_dev;
179 struct phy_device *phydev;
180 bool rx_pause, tx_pause;
181 struct dpaa_priv *priv;
182 u32 newadv, oldadv;
183 int err;
184
185 priv = netdev_priv(net_dev);
186 mac_dev = priv->mac_dev;
187
188 phydev = net_dev->phydev;
189 if (!phydev) {
190 netdev_err(net_dev, "phy device not initialized\n");
191 return -ENODEV;
192 }
193
194 if (!(phydev->supported & SUPPORTED_Pause) ||
195 (!(phydev->supported & SUPPORTED_Asym_Pause) &&
196 (epause->rx_pause != epause->tx_pause)))
197 return -EINVAL;
198
199
200
201
202
203 mac_dev->autoneg_pause = !!epause->autoneg;
204 mac_dev->rx_pause_req = !!epause->rx_pause;
205 mac_dev->tx_pause_req = !!epause->tx_pause;
206
207
208
209
210 newadv = 0;
211 if (epause->rx_pause)
212 newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
213 if (epause->tx_pause)
214 newadv |= ADVERTISED_Asym_Pause;
215
216 oldadv = phydev->advertising &
217 (ADVERTISED_Pause | ADVERTISED_Asym_Pause);
218
219
220
221
222 if (oldadv != newadv) {
223 phydev->advertising &= ~(ADVERTISED_Pause
224 | ADVERTISED_Asym_Pause);
225 phydev->advertising |= newadv;
226 if (phydev->autoneg) {
227 err = phy_start_aneg(phydev);
228 if (err < 0)
229 netdev_err(net_dev, "phy_start_aneg() = %d\n",
230 err);
231 }
232 }
233
234 fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
235 err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
236 if (err < 0)
237 netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
238
239 return err;
240}
241
242static int dpaa_get_sset_count(struct net_device *net_dev, int type)
243{
244 unsigned int total_stats, num_stats;
245
246 num_stats = num_online_cpus() + 1;
247 total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) +
248 DPAA_STATS_GLOBAL_LEN;
249
250 switch (type) {
251 case ETH_SS_STATS:
252 return total_stats;
253 default:
254 return -EOPNOTSUPP;
255 }
256}
257
258static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus,
259 int crr_cpu, u64 *bp_count, u64 *data)
260{
261 int num_values = num_cpus + 1;
262 int crr = 0, j;
263
264
265 data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt;
266 data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt;
267
268 data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets;
269 data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets;
270
271 data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets;
272 data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets;
273
274 data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm;
275 data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm;
276
277 data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs;
278 data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs;
279
280 data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors;
281 data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors;
282
283 data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors;
284 data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors;
285
286 for (j = 0; j < DPAA_BPS_NUM; j++) {
287 data[crr * num_values + crr_cpu] = bp_count[j];
288 data[crr++ * num_values + num_cpus] += bp_count[j];
289 }
290}
291
292static void dpaa_get_ethtool_stats(struct net_device *net_dev,
293 struct ethtool_stats *stats, u64 *data)
294{
295 u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num;
296 struct dpaa_percpu_priv *percpu_priv;
297 struct dpaa_rx_errors rx_errors;
298 unsigned int num_cpus, offset;
299 struct dpaa_ern_cnt ern_cnt;
300 struct dpaa_bp *dpaa_bp;
301 struct dpaa_priv *priv;
302 int total_stats, i, j;
303 bool cg_status;
304
305 total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS);
306 priv = netdev_priv(net_dev);
307 num_cpus = num_online_cpus();
308
309 memset(&bp_count, 0, sizeof(bp_count));
310 memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors));
311 memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt));
312 memset(data, 0, total_stats * sizeof(u64));
313
314 for_each_online_cpu(i) {
315 percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
316 for (j = 0; j < DPAA_BPS_NUM; j++) {
317 dpaa_bp = priv->dpaa_bps[j];
318 if (!dpaa_bp->percpu_count)
319 continue;
320 bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i));
321 }
322 rx_errors.dme += percpu_priv->rx_errors.dme;
323 rx_errors.fpe += percpu_priv->rx_errors.fpe;
324 rx_errors.fse += percpu_priv->rx_errors.fse;
325 rx_errors.phe += percpu_priv->rx_errors.phe;
326
327 ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop;
328 ern_cnt.wred += percpu_priv->ern_cnt.wred;
329 ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond;
330 ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
331 ern_cnt.late_window += percpu_priv->ern_cnt.late_window;
332 ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop;
333 ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired;
334 ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero;
335
336 copy_stats(percpu_priv, num_cpus, i, bp_count, data);
337 }
338
339 offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM);
340 memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors));
341
342 offset += sizeof(struct dpaa_rx_errors) / sizeof(u64);
343 memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt));
344
345
346 cg_num = 0;
347 cg_status = 0;
348 cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies);
349 if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) {
350 cg_num = priv->cgr_data.cgr_congested_count;
351
352
353 priv->cgr_data.congested_jiffies = 0;
354 priv->cgr_data.cgr_congested_count = 0;
355 }
356
357 offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64);
358 data[offset++] = cg_time;
359 data[offset++] = cg_num;
360 data[offset++] = cg_status;
361}
362
363static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
364 u8 *data)
365{
366 unsigned int i, j, num_cpus, size;
367 char string_cpu[ETH_GSTRING_LEN];
368 u8 *strings;
369
370 memset(string_cpu, 0, sizeof(string_cpu));
371 strings = data;
372 num_cpus = num_online_cpus();
373 size = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN;
374
375 for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) {
376 for (j = 0; j < num_cpus; j++) {
377 snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]",
378 dpaa_stats_percpu[i], j);
379 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
380 strings += ETH_GSTRING_LEN;
381 }
382 snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]",
383 dpaa_stats_percpu[i]);
384 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
385 strings += ETH_GSTRING_LEN;
386 }
387 for (i = 0; i < DPAA_BPS_NUM; i++) {
388 for (j = 0; j < num_cpus; j++) {
389 snprintf(string_cpu, ETH_GSTRING_LEN,
390 "bpool %c [CPU %d]", 'a' + i, j);
391 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
392 strings += ETH_GSTRING_LEN;
393 }
394 snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]",
395 'a' + i);
396 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
397 strings += ETH_GSTRING_LEN;
398 }
399 memcpy(strings, dpaa_stats_global, size);
400}
401
402static int dpaa_get_hash_opts(struct net_device *dev,
403 struct ethtool_rxnfc *cmd)
404{
405 struct dpaa_priv *priv = netdev_priv(dev);
406
407 cmd->data = 0;
408
409 switch (cmd->flow_type) {
410 case TCP_V4_FLOW:
411 case TCP_V6_FLOW:
412 case UDP_V4_FLOW:
413 case UDP_V6_FLOW:
414 if (priv->keygen_in_use)
415 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
416
417 case IPV4_FLOW:
418 case IPV6_FLOW:
419 case SCTP_V4_FLOW:
420 case SCTP_V6_FLOW:
421 case AH_ESP_V4_FLOW:
422 case AH_ESP_V6_FLOW:
423 case AH_V4_FLOW:
424 case AH_V6_FLOW:
425 case ESP_V4_FLOW:
426 case ESP_V6_FLOW:
427 if (priv->keygen_in_use)
428 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
429 break;
430 default:
431 cmd->data = 0;
432 break;
433 }
434
435 return 0;
436}
437
438static int dpaa_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
439 u32 *unused)
440{
441 int ret = -EOPNOTSUPP;
442
443 switch (cmd->cmd) {
444 case ETHTOOL_GRXFH:
445 ret = dpaa_get_hash_opts(dev, cmd);
446 break;
447 default:
448 break;
449 }
450
451 return ret;
452}
453
454static void dpaa_set_hash(struct net_device *net_dev, bool enable)
455{
456 struct mac_device *mac_dev;
457 struct fman_port *rxport;
458 struct dpaa_priv *priv;
459
460 priv = netdev_priv(net_dev);
461 mac_dev = priv->mac_dev;
462 rxport = mac_dev->port[0];
463
464 fman_port_use_kg_hash(rxport, enable);
465 priv->keygen_in_use = enable;
466}
467
468static int dpaa_set_hash_opts(struct net_device *dev,
469 struct ethtool_rxnfc *nfc)
470{
471 int ret = -EINVAL;
472
473
474 if (nfc->data &
475 ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
476 return -EINVAL;
477
478 switch (nfc->flow_type) {
479 case TCP_V4_FLOW:
480 case TCP_V6_FLOW:
481 case UDP_V4_FLOW:
482 case UDP_V6_FLOW:
483 case IPV4_FLOW:
484 case IPV6_FLOW:
485 case SCTP_V4_FLOW:
486 case SCTP_V6_FLOW:
487 case AH_ESP_V4_FLOW:
488 case AH_ESP_V6_FLOW:
489 case AH_V4_FLOW:
490 case AH_V6_FLOW:
491 case ESP_V4_FLOW:
492 case ESP_V6_FLOW:
493 dpaa_set_hash(dev, !!nfc->data);
494 ret = 0;
495 break;
496 default:
497 break;
498 }
499
500 return ret;
501}
502
503static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
504{
505 int ret = -EOPNOTSUPP;
506
507 switch (cmd->cmd) {
508 case ETHTOOL_SRXFH:
509 ret = dpaa_set_hash_opts(dev, cmd);
510 break;
511 default:
512 break;
513 }
514
515 return ret;
516}
517
518const struct ethtool_ops dpaa_ethtool_ops = {
519 .get_drvinfo = dpaa_get_drvinfo,
520 .get_msglevel = dpaa_get_msglevel,
521 .set_msglevel = dpaa_set_msglevel,
522 .nway_reset = dpaa_nway_reset,
523 .get_pauseparam = dpaa_get_pauseparam,
524 .set_pauseparam = dpaa_set_pauseparam,
525 .get_link = ethtool_op_get_link,
526 .get_sset_count = dpaa_get_sset_count,
527 .get_ethtool_stats = dpaa_get_ethtool_stats,
528 .get_strings = dpaa_get_strings,
529 .get_link_ksettings = dpaa_get_link_ksettings,
530 .set_link_ksettings = dpaa_set_link_ksettings,
531 .get_rxnfc = dpaa_get_rxnfc,
532 .set_rxnfc = dpaa_set_rxnfc,
533};
534