blob: 1c9fb83b896875a4164c63b46aa0a8f5a1802bf3 [file] [log] [blame]
Jerome Forissiereb48b4b2024-10-16 12:04:08 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2000
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 */
6
7#include <command.h>
8#include <dm/device.h>
9#include <dm/uclass.h>
10#include <net.h>
11#include <linux/compat.h>
12#include <linux/ethtool.h>
13
14static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
15{
16 const struct udevice *current = eth_get_dev();
17 unsigned char env_enetaddr[ARP_HLEN];
18 const struct udevice *dev;
19 struct uclass *uc;
20
21 uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
22 eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
23 printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
24 current == dev ? "active" : "");
25 }
26 return CMD_RET_SUCCESS;
27}
28
29static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
30{
31 int nstats, err, i, off;
32 struct udevice *dev;
33 u64 *values;
34 u8 *strings;
35
36 if (argc < 2)
37 return CMD_RET_USAGE;
38
39 err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
40 if (err) {
41 printf("Could not find device %s\n", argv[1]);
42 return CMD_RET_FAILURE;
43 }
44
45 if (!eth_get_ops(dev)->get_sset_count ||
46 !eth_get_ops(dev)->get_strings ||
47 !eth_get_ops(dev)->get_stats) {
48 printf("Driver does not implement stats dump!\n");
49 return CMD_RET_FAILURE;
50 }
51
52 nstats = eth_get_ops(dev)->get_sset_count(dev);
53 strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
54 if (!strings)
55 return CMD_RET_FAILURE;
56
57 values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
58 if (!values)
59 goto err_free_strings;
60
61 eth_get_ops(dev)->get_strings(dev, strings);
62 eth_get_ops(dev)->get_stats(dev, values);
63
64 off = 0;
65 for (i = 0; i < nstats; i++) {
66 printf(" %s: %llu\n", &strings[off], values[i]);
67 off += ETH_GSTRING_LEN;
68 };
69
70 kfree(strings);
71 kfree(values);
72
73 return CMD_RET_SUCCESS;
74
75err_free_strings:
76 kfree(strings);
77
78 return CMD_RET_FAILURE;
79}
80
81static struct cmd_tbl cmd_net[] = {
82 U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
83 U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
84};
85
86static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
87{
88 struct cmd_tbl *cp;
89
90 cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
91
92 /* Drop the net command */
93 argc--;
94 argv++;
95
96 if (!cp || argc > cp->maxargs)
97 return CMD_RET_USAGE;
98 if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
99 return CMD_RET_SUCCESS;
100
101 return cp->cmd(cmdtp, flag, argc, argv);
102}
103
104U_BOOT_CMD(
105 net, 3, 1, do_net,
106 "NET sub-system",
107 "list - list available devices\n"
108 "stats <device> - dump statistics for specified device\n"
109);