ipq40xx: refresh ess driver and phy with new api
[openwrt/staging/wigyori.git] / target / linux / ipq40xx / files / 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 <linux/version.h>
20 #include "edma.h"
21
22 struct edma_ethtool_stats {
23 uint8_t stat_string[ETH_GSTRING_LEN];
24 uint32_t stat_offset;
25 };
26
27 #define EDMA_STAT(m) offsetof(struct edma_ethtool_statistics, m)
28 #define DRVINFO_LEN 32
29
30 /* Array of strings describing statistics
31 */
32 static const struct edma_ethtool_stats edma_gstrings_stats[] = {
33 {"tx_q0_pkt", EDMA_STAT(tx_q0_pkt)},
34 {"tx_q1_pkt", EDMA_STAT(tx_q1_pkt)},
35 {"tx_q2_pkt", EDMA_STAT(tx_q2_pkt)},
36 {"tx_q3_pkt", EDMA_STAT(tx_q3_pkt)},
37 {"tx_q4_pkt", EDMA_STAT(tx_q4_pkt)},
38 {"tx_q5_pkt", EDMA_STAT(tx_q5_pkt)},
39 {"tx_q6_pkt", EDMA_STAT(tx_q6_pkt)},
40 {"tx_q7_pkt", EDMA_STAT(tx_q7_pkt)},
41 {"tx_q8_pkt", EDMA_STAT(tx_q8_pkt)},
42 {"tx_q9_pkt", EDMA_STAT(tx_q9_pkt)},
43 {"tx_q10_pkt", EDMA_STAT(tx_q10_pkt)},
44 {"tx_q11_pkt", EDMA_STAT(tx_q11_pkt)},
45 {"tx_q12_pkt", EDMA_STAT(tx_q12_pkt)},
46 {"tx_q13_pkt", EDMA_STAT(tx_q13_pkt)},
47 {"tx_q14_pkt", EDMA_STAT(tx_q14_pkt)},
48 {"tx_q15_pkt", EDMA_STAT(tx_q15_pkt)},
49 {"tx_q0_byte", EDMA_STAT(tx_q0_byte)},
50 {"tx_q1_byte", EDMA_STAT(tx_q1_byte)},
51 {"tx_q2_byte", EDMA_STAT(tx_q2_byte)},
52 {"tx_q3_byte", EDMA_STAT(tx_q3_byte)},
53 {"tx_q4_byte", EDMA_STAT(tx_q4_byte)},
54 {"tx_q5_byte", EDMA_STAT(tx_q5_byte)},
55 {"tx_q6_byte", EDMA_STAT(tx_q6_byte)},
56 {"tx_q7_byte", EDMA_STAT(tx_q7_byte)},
57 {"tx_q8_byte", EDMA_STAT(tx_q8_byte)},
58 {"tx_q9_byte", EDMA_STAT(tx_q9_byte)},
59 {"tx_q10_byte", EDMA_STAT(tx_q10_byte)},
60 {"tx_q11_byte", EDMA_STAT(tx_q11_byte)},
61 {"tx_q12_byte", EDMA_STAT(tx_q12_byte)},
62 {"tx_q13_byte", EDMA_STAT(tx_q13_byte)},
63 {"tx_q14_byte", EDMA_STAT(tx_q14_byte)},
64 {"tx_q15_byte", EDMA_STAT(tx_q15_byte)},
65 {"rx_q0_pkt", EDMA_STAT(rx_q0_pkt)},
66 {"rx_q1_pkt", EDMA_STAT(rx_q1_pkt)},
67 {"rx_q2_pkt", EDMA_STAT(rx_q2_pkt)},
68 {"rx_q3_pkt", EDMA_STAT(rx_q3_pkt)},
69 {"rx_q4_pkt", EDMA_STAT(rx_q4_pkt)},
70 {"rx_q5_pkt", EDMA_STAT(rx_q5_pkt)},
71 {"rx_q6_pkt", EDMA_STAT(rx_q6_pkt)},
72 {"rx_q7_pkt", EDMA_STAT(rx_q7_pkt)},
73 {"rx_q0_byte", EDMA_STAT(rx_q0_byte)},
74 {"rx_q1_byte", EDMA_STAT(rx_q1_byte)},
75 {"rx_q2_byte", EDMA_STAT(rx_q2_byte)},
76 {"rx_q3_byte", EDMA_STAT(rx_q3_byte)},
77 {"rx_q4_byte", EDMA_STAT(rx_q4_byte)},
78 {"rx_q5_byte", EDMA_STAT(rx_q5_byte)},
79 {"rx_q6_byte", EDMA_STAT(rx_q6_byte)},
80 {"rx_q7_byte", EDMA_STAT(rx_q7_byte)},
81 {"tx_desc_error", EDMA_STAT(tx_desc_error)},
82 {"rx_alloc_fail_ctr", EDMA_STAT(rx_alloc_fail_ctr)},
83 };
84
85 #define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats)
86
87 /* edma_get_strset_count()
88 * Get strset count
89 */
90 static int edma_get_strset_count(struct net_device *netdev,
91 int sset)
92 {
93 switch (sset) {
94 case ETH_SS_STATS:
95 return EDMA_STATS_LEN;
96 default:
97 netdev_dbg(netdev, "%s: Invalid string set", __func__);
98 return -EOPNOTSUPP;
99 }
100 }
101
102
103 /* edma_get_strings()
104 * get stats string
105 */
106 static void edma_get_strings(struct net_device *netdev, uint32_t stringset,
107 uint8_t *data)
108 {
109 uint8_t *p = data;
110 uint32_t i;
111
112 switch (stringset) {
113 case ETH_SS_STATS:
114 for (i = 0; i < EDMA_STATS_LEN; i++) {
115 memcpy(p, edma_gstrings_stats[i].stat_string,
116 min((size_t)ETH_GSTRING_LEN,
117 strlen(edma_gstrings_stats[i].stat_string)
118 + 1));
119 p += ETH_GSTRING_LEN;
120 }
121 break;
122 }
123 }
124
125 /* edma_get_ethtool_stats()
126 * Get ethtool statistics
127 */
128 static void edma_get_ethtool_stats(struct net_device *netdev,
129 struct ethtool_stats *stats, uint64_t *data)
130 {
131 struct edma_adapter *adapter = netdev_priv(netdev);
132 struct edma_common_info *edma_cinfo = adapter->edma_cinfo;
133 int i;
134 uint8_t *p = NULL;
135
136 edma_read_append_stats(edma_cinfo);
137
138 for(i = 0; i < EDMA_STATS_LEN; i++) {
139 p = (uint8_t *)&(edma_cinfo->edma_ethstats) +
140 edma_gstrings_stats[i].stat_offset;
141 data[i] = *(uint32_t *)p;
142 }
143 }
144
145 /* edma_get_drvinfo()
146 * get edma driver info
147 */
148 static void edma_get_drvinfo(struct net_device *dev,
149 struct ethtool_drvinfo *info)
150 {
151 strlcpy(info->driver, "ess_edma", DRVINFO_LEN);
152 strlcpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN);
153 }
154
155 /* edma_nway_reset()
156 * Reset the phy, if available.
157 */
158 static int edma_nway_reset(struct net_device *netdev)
159 {
160 return -EINVAL;
161 }
162
163 /* edma_get_wol()
164 * get wake on lan info
165 */
166 static void edma_get_wol(struct net_device *netdev,
167 struct ethtool_wolinfo *wol)
168 {
169 wol->supported = 0;
170 wol->wolopts = 0;
171 }
172
173 /* edma_get_msglevel()
174 * get message level.
175 */
176 static uint32_t edma_get_msglevel(struct net_device *netdev)
177 {
178 return 0;
179 }
180
181 /* edma_get_settings()
182 * Get edma settings
183 */
184 static int edma_get_settings(struct net_device *netdev,
185 struct ethtool_link_ksettings *cmd)
186 {
187 struct edma_adapter *adapter = netdev_priv(netdev);
188
189 if (adapter->poll_required) {
190 if ((adapter->forced_speed != SPEED_UNKNOWN)
191 && !(adapter->poll_required))
192 return -EPERM;
193
194 phy_ethtool_ksettings_get(adapter->phydev, cmd);
195 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, adapter->phydev->advertising))
196 cmd->base.port = PORT_FIBRE;
197 else
198 cmd->base.port = PORT_TP;
199 } else {
200 /* If the speed/duplex for this GMAC is forced and we
201 * are not polling for link state changes, return the
202 * values as specified by platform. This will be true
203 * for GMACs connected to switch, and interfaces that
204 * do not use a PHY.
205 */
206 if (!(adapter->poll_required)) {
207 if (adapter->forced_speed != SPEED_UNKNOWN) {
208 /* set speed and duplex */
209 cmd->base.speed = SPEED_1000;
210 cmd->base.duplex = DUPLEX_FULL;
211
212 /* Populate capabilities advertised by self */
213 linkmode_zero(cmd->link_modes.advertising);
214 cmd->base.autoneg = 0;
215 cmd->base.port = PORT_TP;
216 cmd->base.transceiver = XCVR_EXTERNAL;
217 } else {
218 /* non link polled and non
219 * forced speed/duplex interface
220 */
221 return -EIO;
222 }
223 }
224 }
225
226 return 0;
227 }
228
229 /* edma_set_settings()
230 * Set EDMA settings
231 */
232 static int edma_set_settings(struct net_device *netdev,
233 const struct ethtool_link_ksettings *cmd)
234 {
235 struct edma_adapter *adapter = netdev_priv(netdev);
236
237 if ((adapter->forced_speed != SPEED_UNKNOWN) &&
238 !adapter->poll_required)
239 return -EPERM;
240
241 return phy_ethtool_ksettings_set(adapter->phydev, cmd);
242 }
243
244 /* edma_get_coalesce
245 * get interrupt mitigation
246 */
247 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)
248 static int edma_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec,
249 struct kernel_ethtool_coalesce *kernel_coal,
250 struct netlink_ext_ack *extack)
251 #else
252 static int edma_get_coalesce(struct net_device *netdev,
253 struct ethtool_coalesce *ec)
254 #endif
255 {
256 u32 reg_val;
257
258 edma_get_tx_rx_coalesce(&reg_val);
259
260 /* We read the Interrupt Moderation Timer(IMT) register value,
261 * use lower 16 bit for rx and higher 16 bit for Tx. We do a
262 * left shift by 1, because IMT resolution timer is 2usecs.
263 * Hence the value given by the register is multiplied by 2 to
264 * get the actual time in usecs.
265 */
266 ec->tx_coalesce_usecs = (((reg_val >> 16) & 0xffff) << 1);
267 ec->rx_coalesce_usecs = ((reg_val & 0xffff) << 1);
268
269 return 0;
270 }
271
272 /* edma_set_coalesce
273 * set interrupt mitigation
274 */
275 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)
276 static int edma_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec,
277 struct kernel_ethtool_coalesce *kernel_coal,
278 struct netlink_ext_ack *extack)
279 #else
280 static int edma_set_coalesce(struct net_device *netdev,
281 struct ethtool_coalesce *ec)
282 #endif
283 {
284 if (ec->tx_coalesce_usecs)
285 edma_change_tx_coalesce(ec->tx_coalesce_usecs);
286 if (ec->rx_coalesce_usecs)
287 edma_change_rx_coalesce(ec->rx_coalesce_usecs);
288
289 return 0;
290 }
291
292 /* edma_set_priv_flags()
293 * Set EDMA private flags
294 */
295 static int edma_set_priv_flags(struct net_device *netdev, u32 flags)
296 {
297 return 0;
298 }
299
300 /* edma_get_priv_flags()
301 * get edma driver flags
302 */
303 static u32 edma_get_priv_flags(struct net_device *netdev)
304 {
305 return 0;
306 }
307
308 /* edma_get_ringparam()
309 * get ring size
310 */
311 static void edma_get_ringparam(struct net_device *netdev,
312 struct ethtool_ringparam *ring)
313 {
314 struct edma_adapter *adapter = netdev_priv(netdev);
315 struct edma_common_info *edma_cinfo = adapter->edma_cinfo;
316
317 ring->tx_max_pending = edma_cinfo->tx_ring_count;
318 ring->rx_max_pending = edma_cinfo->rx_ring_count;
319 }
320
321 /* Ethtool operations
322 */
323 static const struct ethtool_ops edma_ethtool_ops = {
324 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
325 .supported_coalesce_params = ETHTOOL_COALESCE_USECS,
326 #endif
327 .get_drvinfo = &edma_get_drvinfo,
328 .get_link = &ethtool_op_get_link,
329 .get_msglevel = &edma_get_msglevel,
330 .nway_reset = &edma_nway_reset,
331 .get_wol = &edma_get_wol,
332 .get_link_ksettings = &edma_get_settings,
333 .set_link_ksettings = &edma_set_settings,
334 .get_strings = &edma_get_strings,
335 .get_sset_count = &edma_get_strset_count,
336 .get_ethtool_stats = &edma_get_ethtool_stats,
337 .get_coalesce = &edma_get_coalesce,
338 .set_coalesce = &edma_set_coalesce,
339 .get_priv_flags = edma_get_priv_flags,
340 .set_priv_flags = edma_set_priv_flags,
341 .get_ringparam = edma_get_ringparam,
342 };
343
344 /* edma_set_ethtool_ops
345 * Set ethtool operations
346 */
347 void edma_set_ethtool_ops(struct net_device *netdev)
348 {
349 netdev->ethtool_ops = &edma_ethtool_ops;
350 }