1270e20a90cc115f097fd40b675808913701c407
[openwrt/openwrt.git] / target / linux / ipq40xx / files-5.4 / drivers / net / ethernet / qualcomm / essedma / edma_ethtool.c
1 /*
2 * Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <linux/ethtool.h>
17 #include <linux/netdevice.h>
18 #include <linux/string.h>
19 #include "edma.h"
20
21 struct edma_ethtool_stats {
22 uint8_t stat_string[ETH_GSTRING_LEN];
23 uint32_t stat_offset;
24 };
25
26 #define EDMA_STAT(m) offsetof(struct edma_ethtool_statistics, m)
27 #define DRVINFO_LEN 32
28
29 /* Array of strings describing statistics
30 */
31 static const struct edma_ethtool_stats edma_gstrings_stats[] = {
32 {"tx_q0_pkt", EDMA_STAT(tx_q0_pkt)},
33 {"tx_q1_pkt", EDMA_STAT(tx_q1_pkt)},
34 {"tx_q2_pkt", EDMA_STAT(tx_q2_pkt)},
35 {"tx_q3_pkt", EDMA_STAT(tx_q3_pkt)},
36 {"tx_q4_pkt", EDMA_STAT(tx_q4_pkt)},
37 {"tx_q5_pkt", EDMA_STAT(tx_q5_pkt)},
38 {"tx_q6_pkt", EDMA_STAT(tx_q6_pkt)},
39 {"tx_q7_pkt", EDMA_STAT(tx_q7_pkt)},
40 {"tx_q8_pkt", EDMA_STAT(tx_q8_pkt)},
41 {"tx_q9_pkt", EDMA_STAT(tx_q9_pkt)},
42 {"tx_q10_pkt", EDMA_STAT(tx_q10_pkt)},
43 {"tx_q11_pkt", EDMA_STAT(tx_q11_pkt)},
44 {"tx_q12_pkt", EDMA_STAT(tx_q12_pkt)},
45 {"tx_q13_pkt", EDMA_STAT(tx_q13_pkt)},
46 {"tx_q14_pkt", EDMA_STAT(tx_q14_pkt)},
47 {"tx_q15_pkt", EDMA_STAT(tx_q15_pkt)},
48 {"tx_q0_byte", EDMA_STAT(tx_q0_byte)},
49 {"tx_q1_byte", EDMA_STAT(tx_q1_byte)},
50 {"tx_q2_byte", EDMA_STAT(tx_q2_byte)},
51 {"tx_q3_byte", EDMA_STAT(tx_q3_byte)},
52 {"tx_q4_byte", EDMA_STAT(tx_q4_byte)},
53 {"tx_q5_byte", EDMA_STAT(tx_q5_byte)},
54 {"tx_q6_byte", EDMA_STAT(tx_q6_byte)},
55 {"tx_q7_byte", EDMA_STAT(tx_q7_byte)},
56 {"tx_q8_byte", EDMA_STAT(tx_q8_byte)},
57 {"tx_q9_byte", EDMA_STAT(tx_q9_byte)},
58 {"tx_q10_byte", EDMA_STAT(tx_q10_byte)},
59 {"tx_q11_byte", EDMA_STAT(tx_q11_byte)},
60 {"tx_q12_byte", EDMA_STAT(tx_q12_byte)},
61 {"tx_q13_byte", EDMA_STAT(tx_q13_byte)},
62 {"tx_q14_byte", EDMA_STAT(tx_q14_byte)},
63 {"tx_q15_byte", EDMA_STAT(tx_q15_byte)},
64 {"rx_q0_pkt", EDMA_STAT(rx_q0_pkt)},
65 {"rx_q1_pkt", EDMA_STAT(rx_q1_pkt)},
66 {"rx_q2_pkt", EDMA_STAT(rx_q2_pkt)},
67 {"rx_q3_pkt", EDMA_STAT(rx_q3_pkt)},
68 {"rx_q4_pkt", EDMA_STAT(rx_q4_pkt)},
69 {"rx_q5_pkt", EDMA_STAT(rx_q5_pkt)},
70 {"rx_q6_pkt", EDMA_STAT(rx_q6_pkt)},
71 {"rx_q7_pkt", EDMA_STAT(rx_q7_pkt)},
72 {"rx_q0_byte", EDMA_STAT(rx_q0_byte)},
73 {"rx_q1_byte", EDMA_STAT(rx_q1_byte)},
74 {"rx_q2_byte", EDMA_STAT(rx_q2_byte)},
75 {"rx_q3_byte", EDMA_STAT(rx_q3_byte)},
76 {"rx_q4_byte", EDMA_STAT(rx_q4_byte)},
77 {"rx_q5_byte", EDMA_STAT(rx_q5_byte)},
78 {"rx_q6_byte", EDMA_STAT(rx_q6_byte)},
79 {"rx_q7_byte", EDMA_STAT(rx_q7_byte)},
80 {"tx_desc_error", EDMA_STAT(tx_desc_error)},
81 {"rx_alloc_fail_ctr", EDMA_STAT(rx_alloc_fail_ctr)},
82 };
83
84 #define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats)
85
86 /* edma_get_strset_count()
87 * Get strset count
88 */
89 static int edma_get_strset_count(struct net_device *netdev,
90 int sset)
91 {
92 switch (sset) {
93 case ETH_SS_STATS:
94 return EDMA_STATS_LEN;
95 default:
96 netdev_dbg(netdev, "%s: Invalid string set", __func__);
97 return -EOPNOTSUPP;
98 }
99 }
100
101
102 /* edma_get_strings()
103 * get stats string
104 */
105 static void edma_get_strings(struct net_device *netdev, uint32_t stringset,
106 uint8_t *data)
107 {
108 uint8_t *p = data;
109 uint32_t i;
110
111 switch (stringset) {
112 case ETH_SS_STATS:
113 for (i = 0; i < EDMA_STATS_LEN; i++) {
114 memcpy(p, edma_gstrings_stats[i].stat_string,
115 min((size_t)ETH_GSTRING_LEN,
116 strlen(edma_gstrings_stats[i].stat_string)
117 + 1));
118 p += ETH_GSTRING_LEN;
119 }
120 break;
121 }
122 }
123
124 /* edma_get_ethtool_stats()
125 * Get ethtool statistics
126 */
127 static void edma_get_ethtool_stats(struct net_device *netdev,
128 struct ethtool_stats *stats, uint64_t *data)
129 {
130 struct edma_adapter *adapter = netdev_priv(netdev);
131 struct edma_common_info *edma_cinfo = adapter->edma_cinfo;
132 int i;
133 uint8_t *p = NULL;
134
135 edma_read_append_stats(edma_cinfo);
136
137 for(i = 0; i < EDMA_STATS_LEN; i++) {
138 p = (uint8_t *)&(edma_cinfo->edma_ethstats) +
139 edma_gstrings_stats[i].stat_offset;
140 data[i] = *(uint32_t *)p;
141 }
142 }
143
144 /* edma_get_drvinfo()
145 * get edma driver info
146 */
147 static void edma_get_drvinfo(struct net_device *dev,
148 struct ethtool_drvinfo *info)
149 {
150 strlcpy(info->driver, "ess_edma", DRVINFO_LEN);
151 strlcpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN);
152 }
153
154 /* edma_nway_reset()
155 * Reset the phy, if available.
156 */
157 static int edma_nway_reset(struct net_device *netdev)
158 {
159 return -EINVAL;
160 }
161
162 /* edma_get_wol()
163 * get wake on lan info
164 */
165 static void edma_get_wol(struct net_device *netdev,
166 struct ethtool_wolinfo *wol)
167 {
168 wol->supported = 0;
169 wol->wolopts = 0;
170 }
171
172 /* edma_get_msglevel()
173 * get message level.
174 */
175 static uint32_t edma_get_msglevel(struct net_device *netdev)
176 {
177 return 0;
178 }
179
180 /* edma_get_settings()
181 * Get edma settings
182 */
183 static int edma_get_settings(struct net_device *netdev,
184 struct ethtool_link_ksettings *cmd)
185 {
186 struct edma_adapter *adapter = netdev_priv(netdev);
187
188 if (adapter->poll_required) {
189 struct phy_device *phydev = NULL;
190 uint16_t phyreg;
191
192 if ((adapter->forced_speed != SPEED_UNKNOWN)
193 && !(adapter->poll_required))
194 return -EPERM;
195
196 phydev = adapter->phydev;
197
198 linkmode_copy(cmd->link_modes.advertising, phydev->advertising);
199 linkmode_copy(cmd->link_modes.supported, phydev->supported);
200
201 cmd->base.autoneg = phydev->autoneg;
202
203 if (adapter->link_state == __EDMA_LINKDOWN) {
204 cmd->base.speed = SPEED_UNKNOWN;
205 cmd->base.duplex = DUPLEX_UNKNOWN;
206 } else {
207 cmd->base.speed = phydev->speed;
208 cmd->base.duplex = phydev->duplex;
209 }
210
211 cmd->base.phy_address = adapter->phy_mdio_addr;
212
213 phyreg = (uint16_t)phy_read(adapter->phydev, MII_LPA);
214 if (phyreg & LPA_10HALF)
215 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
216 cmd->link_modes.lp_advertising);
217
218 if (phyreg & LPA_10FULL)
219 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
220 cmd->link_modes.lp_advertising);
221
222 if (phyreg & LPA_100HALF)
223 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
224 cmd->link_modes.lp_advertising);
225
226 if (phyreg & LPA_100FULL)
227 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
228 cmd->link_modes.lp_advertising);
229
230 phyreg = (uint16_t)phy_read(adapter->phydev, MII_STAT1000);
231 if (phyreg & LPA_1000HALF)
232 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
233 cmd->link_modes.lp_advertising);
234
235 if (phyreg & LPA_1000FULL)
236 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
237 cmd->link_modes.lp_advertising);
238 } else {
239 /* If the speed/duplex for this GMAC is forced and we
240 * are not polling for link state changes, return the
241 * values as specified by platform. This will be true
242 * for GMACs connected to switch, and interfaces that
243 * do not use a PHY.
244 */
245 if (!(adapter->poll_required)) {
246 if (adapter->forced_speed != SPEED_UNKNOWN) {
247 /* set speed and duplex */
248 cmd->base.speed = SPEED_1000;
249 cmd->base.duplex = DUPLEX_FULL;
250
251 /* Populate capabilities advertised by self */
252 linkmode_zero(cmd->link_modes.advertising);
253 cmd->base.autoneg = 0;
254 cmd->base.port = PORT_TP;
255 cmd->base.transceiver = XCVR_EXTERNAL;
256 } else {
257 /* non link polled and non
258 * forced speed/duplex interface
259 */
260 return -EIO;
261 }
262 }
263 }
264
265 return 0;
266 }
267
268 /* edma_set_settings()
269 * Set EDMA settings
270 */
271 static int edma_set_settings(struct net_device *netdev,
272 const struct ethtool_link_ksettings *cmd)
273 {
274 struct edma_adapter *adapter = netdev_priv(netdev);
275 struct phy_device *phydev = NULL;
276
277 if ((adapter->forced_speed != SPEED_UNKNOWN) &&
278 !adapter->poll_required)
279 return -EPERM;
280
281 phydev = adapter->phydev;
282 linkmode_copy(phydev->advertising, cmd->link_modes.advertising);
283 linkmode_copy(phydev->supported, cmd->link_modes.supported);
284 phydev->autoneg = cmd->base.autoneg;
285 phydev->speed = cmd->base.speed;
286 phydev->duplex = cmd->base.duplex;
287
288 genphy_config_aneg(phydev);
289
290 return 0;
291 }
292
293 /* edma_get_coalesce
294 * get interrupt mitigation
295 */
296 static int edma_get_coalesce(struct net_device *netdev,
297 struct ethtool_coalesce *ec)
298 {
299 u32 reg_val;
300
301 edma_get_tx_rx_coalesce(&reg_val);
302
303 /* We read the Interrupt Moderation Timer(IMT) register value,
304 * use lower 16 bit for rx and higher 16 bit for Tx. We do a
305 * left shift by 1, because IMT resolution timer is 2usecs.
306 * Hence the value given by the register is multiplied by 2 to
307 * get the actual time in usecs.
308 */
309 ec->tx_coalesce_usecs = (((reg_val >> 16) & 0xffff) << 1);
310 ec->rx_coalesce_usecs = ((reg_val & 0xffff) << 1);
311
312 return 0;
313 }
314
315 /* edma_set_coalesce
316 * set interrupt mitigation
317 */
318 static int edma_set_coalesce(struct net_device *netdev,
319 struct ethtool_coalesce *ec)
320 {
321 if (ec->tx_coalesce_usecs)
322 edma_change_tx_coalesce(ec->tx_coalesce_usecs);
323 if (ec->rx_coalesce_usecs)
324 edma_change_rx_coalesce(ec->rx_coalesce_usecs);
325
326 return 0;
327 }
328
329 /* edma_set_priv_flags()
330 * Set EDMA private flags
331 */
332 static int edma_set_priv_flags(struct net_device *netdev, u32 flags)
333 {
334 return 0;
335 }
336
337 /* edma_get_priv_flags()
338 * get edma driver flags
339 */
340 static u32 edma_get_priv_flags(struct net_device *netdev)
341 {
342 return 0;
343 }
344
345 /* edma_get_ringparam()
346 * get ring size
347 */
348 static void edma_get_ringparam(struct net_device *netdev,
349 struct ethtool_ringparam *ring)
350 {
351 struct edma_adapter *adapter = netdev_priv(netdev);
352 struct edma_common_info *edma_cinfo = adapter->edma_cinfo;
353
354 ring->tx_max_pending = edma_cinfo->tx_ring_count;
355 ring->rx_max_pending = edma_cinfo->rx_ring_count;
356 }
357
358 /* Ethtool operations
359 */
360 static const struct ethtool_ops edma_ethtool_ops = {
361 .get_drvinfo = &edma_get_drvinfo,
362 .get_link = &ethtool_op_get_link,
363 .get_msglevel = &edma_get_msglevel,
364 .nway_reset = &edma_nway_reset,
365 .get_wol = &edma_get_wol,
366 .get_link_ksettings = &edma_get_settings,
367 .set_link_ksettings = &edma_set_settings,
368 .get_strings = &edma_get_strings,
369 .get_sset_count = &edma_get_strset_count,
370 .get_ethtool_stats = &edma_get_ethtool_stats,
371 .get_coalesce = &edma_get_coalesce,
372 .set_coalesce = &edma_set_coalesce,
373 .get_priv_flags = edma_get_priv_flags,
374 .set_priv_flags = edma_set_priv_flags,
375 .get_ringparam = edma_get_ringparam,
376 };
377
378 /* edma_set_ethtool_ops
379 * Set ethtool operations
380 */
381 void edma_set_ethtool_ops(struct net_device *netdev)
382 {
383 netdev->ethtool_ops = &edma_ethtool_ops;
384 }