1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Applied Micro X-Gene SoC Ethernet v2 Driver |
4 | * |
5 | * Copyright (c) 2017, Applied Micro Circuits Corporation |
6 | * Author(s): Iyappan Subramanian <isubramanian@apm.com> |
7 | * Keyur Chudgar <kchudgar@apm.com> |
8 | */ |
9 | |
10 | #include "main.h" |
11 | |
12 | #define XGE_STAT(m) { #m, offsetof(struct xge_pdata, stats.m) } |
13 | #define XGE_EXTD_STAT(m, n) \ |
14 | { \ |
15 | #m, \ |
16 | n, \ |
17 | 0 \ |
18 | } |
19 | |
20 | static const struct xge_gstrings_stats gstrings_stats[] = { |
21 | XGE_STAT(rx_packets), |
22 | XGE_STAT(tx_packets), |
23 | XGE_STAT(rx_bytes), |
24 | XGE_STAT(tx_bytes), |
25 | XGE_STAT(rx_errors) |
26 | }; |
27 | |
28 | static struct xge_gstrings_extd_stats gstrings_extd_stats[] = { |
29 | XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64), |
30 | XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127), |
31 | XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255), |
32 | XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511), |
33 | XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K), |
34 | XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX), |
35 | XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV), |
36 | XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS), |
37 | XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA), |
38 | XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA), |
39 | XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF), |
40 | XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF), |
41 | XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO), |
42 | XGE_EXTD_STAT(rx_align_err_cntr, RALN), |
43 | XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR), |
44 | XGE_EXTD_STAT(rx_code_err_cntr, RCDE), |
45 | XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE), |
46 | XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND), |
47 | XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR), |
48 | XGE_EXTD_STAT(rx_fragments_cntr, RFRG), |
49 | XGE_EXTD_STAT(rx_jabber_cntr, RJBR), |
50 | XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP), |
51 | XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA), |
52 | XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA), |
53 | XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF), |
54 | XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR), |
55 | XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF), |
56 | XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL), |
57 | XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL), |
58 | XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL), |
59 | XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL), |
60 | XGE_EXTD_STAT(tx_total_col_cntr, TNCL), |
61 | XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH), |
62 | XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP), |
63 | XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR), |
64 | XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS), |
65 | XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF), |
66 | XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR), |
67 | XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND), |
68 | XGE_EXTD_STAT(tx_fragments_cntr, TFRG) |
69 | }; |
70 | |
71 | #define XGE_STATS_LEN ARRAY_SIZE(gstrings_stats) |
72 | #define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats) |
73 | |
74 | static void xge_mac_get_extd_stats(struct xge_pdata *pdata) |
75 | { |
76 | u32 data; |
77 | int i; |
78 | |
79 | for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { |
80 | data = xge_rd_csr(pdata, offset: gstrings_extd_stats[i].addr); |
81 | gstrings_extd_stats[i].value += data; |
82 | } |
83 | } |
84 | |
85 | static void xge_get_drvinfo(struct net_device *ndev, |
86 | struct ethtool_drvinfo *info) |
87 | { |
88 | struct xge_pdata *pdata = netdev_priv(dev: ndev); |
89 | struct platform_device *pdev = pdata->pdev; |
90 | |
91 | strcpy(p: info->driver, q: "xgene-enet-v2" ); |
92 | sprintf(buf: info->bus_info, fmt: "%s" , pdev->name); |
93 | } |
94 | |
95 | static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data) |
96 | { |
97 | u8 *p = data; |
98 | int i; |
99 | |
100 | if (stringset != ETH_SS_STATS) |
101 | return; |
102 | |
103 | for (i = 0; i < XGE_STATS_LEN; i++) { |
104 | memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); |
105 | p += ETH_GSTRING_LEN; |
106 | } |
107 | |
108 | for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { |
109 | memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN); |
110 | p += ETH_GSTRING_LEN; |
111 | } |
112 | } |
113 | |
114 | static int xge_get_sset_count(struct net_device *ndev, int sset) |
115 | { |
116 | if (sset != ETH_SS_STATS) |
117 | return -EINVAL; |
118 | |
119 | return XGE_STATS_LEN + XGE_EXTD_STATS_LEN; |
120 | } |
121 | |
122 | static void xge_get_ethtool_stats(struct net_device *ndev, |
123 | struct ethtool_stats *dummy, |
124 | u64 *data) |
125 | { |
126 | void *pdata = netdev_priv(dev: ndev); |
127 | int i; |
128 | |
129 | for (i = 0; i < XGE_STATS_LEN; i++) |
130 | *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); |
131 | |
132 | xge_mac_get_extd_stats(pdata); |
133 | |
134 | for (i = 0; i < XGE_EXTD_STATS_LEN; i++) |
135 | *data++ = gstrings_extd_stats[i].value; |
136 | } |
137 | |
138 | static int xge_get_link_ksettings(struct net_device *ndev, |
139 | struct ethtool_link_ksettings *cmd) |
140 | { |
141 | struct phy_device *phydev = ndev->phydev; |
142 | |
143 | if (!phydev) |
144 | return -ENODEV; |
145 | |
146 | phy_ethtool_ksettings_get(phydev, cmd); |
147 | |
148 | return 0; |
149 | } |
150 | |
151 | static int xge_set_link_ksettings(struct net_device *ndev, |
152 | const struct ethtool_link_ksettings *cmd) |
153 | { |
154 | struct phy_device *phydev = ndev->phydev; |
155 | |
156 | if (!phydev) |
157 | return -ENODEV; |
158 | |
159 | return phy_ethtool_ksettings_set(phydev, cmd); |
160 | } |
161 | |
162 | static const struct ethtool_ops xge_ethtool_ops = { |
163 | .get_drvinfo = xge_get_drvinfo, |
164 | .get_link = ethtool_op_get_link, |
165 | .get_strings = xge_get_strings, |
166 | .get_sset_count = xge_get_sset_count, |
167 | .get_ethtool_stats = xge_get_ethtool_stats, |
168 | .get_link_ksettings = xge_get_link_ksettings, |
169 | .set_link_ksettings = xge_set_link_ksettings, |
170 | }; |
171 | |
172 | void xge_set_ethtool_ops(struct net_device *ndev) |
173 | { |
174 | ndev->ethtool_ops = &xge_ethtool_ops; |
175 | } |
176 | |