treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 284
[linux-block.git] / drivers / net / ethernet / qualcomm / emac / emac-ethtool.c
CommitLineData
97fb5e8d 1// SPDX-License-Identifier: GPL-2.0-only
79f664ed 2/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
79f664ed
TT
3 */
4
5#include <linux/ethtool.h>
6#include <linux/phy.h>
7
8#include "emac.h"
9
10static const char * const emac_ethtool_stat_strings[] = {
11 "rx_ok",
12 "rx_bcast",
13 "rx_mcast",
14 "rx_pause",
15 "rx_ctrl",
16 "rx_fcs_err",
17 "rx_len_err",
18 "rx_byte_cnt",
19 "rx_runt",
20 "rx_frag",
21 "rx_sz_64",
22 "rx_sz_65_127",
23 "rx_sz_128_255",
24 "rx_sz_256_511",
25 "rx_sz_512_1023",
26 "rx_sz_1024_1518",
27 "rx_sz_1519_max",
28 "rx_sz_ov",
29 "rx_rxf_ov",
30 "rx_align_err",
31 "rx_bcast_byte_cnt",
32 "rx_mcast_byte_cnt",
33 "rx_err_addr",
34 "rx_crc_align",
35 "rx_jabbers",
36 "tx_ok",
37 "tx_bcast",
38 "tx_mcast",
39 "tx_pause",
40 "tx_exc_defer",
41 "tx_ctrl",
42 "tx_defer",
43 "tx_byte_cnt",
44 "tx_sz_64",
45 "tx_sz_65_127",
46 "tx_sz_128_255",
47 "tx_sz_256_511",
48 "tx_sz_512_1023",
49 "tx_sz_1024_1518",
50 "tx_sz_1519_max",
51 "tx_1_col",
52 "tx_2_col",
53 "tx_late_col",
54 "tx_abort_col",
55 "tx_underrun",
56 "tx_rd_eop",
57 "tx_len_err",
58 "tx_trunc",
59 "tx_bcast_byte",
60 "tx_mcast_byte",
61 "tx_col",
62};
63
64#define EMAC_STATS_LEN ARRAY_SIZE(emac_ethtool_stat_strings)
65
66static u32 emac_get_msglevel(struct net_device *netdev)
67{
68 struct emac_adapter *adpt = netdev_priv(netdev);
69
70 return adpt->msg_enable;
71}
72
73static void emac_set_msglevel(struct net_device *netdev, u32 data)
74{
75 struct emac_adapter *adpt = netdev_priv(netdev);
76
77 adpt->msg_enable = data;
78}
79
80static int emac_get_sset_count(struct net_device *netdev, int sset)
81{
82 switch (sset) {
4a7a3860
TT
83 case ETH_SS_PRIV_FLAGS:
84 return 1;
79f664ed
TT
85 case ETH_SS_STATS:
86 return EMAC_STATS_LEN;
87 default:
88 return -EOPNOTSUPP;
89 }
90}
91
92static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
93{
94 unsigned int i;
95
96 switch (stringset) {
4a7a3860
TT
97 case ETH_SS_PRIV_FLAGS:
98 strcpy(data, "single-pause-mode");
99 break;
100
79f664ed
TT
101 case ETH_SS_STATS:
102 for (i = 0; i < EMAC_STATS_LEN; i++) {
103 strlcpy(data, emac_ethtool_stat_strings[i],
104 ETH_GSTRING_LEN);
105 data += ETH_GSTRING_LEN;
106 }
107 break;
108 }
109}
110
111static void emac_get_ethtool_stats(struct net_device *netdev,
112 struct ethtool_stats *stats,
113 u64 *data)
114{
115 struct emac_adapter *adpt = netdev_priv(netdev);
116
117 spin_lock(&adpt->stats.lock);
118
119 emac_update_hw_stats(adpt);
120 memcpy(data, &adpt->stats, EMAC_STATS_LEN * sizeof(u64));
121
122 spin_unlock(&adpt->stats.lock);
123}
124
125static int emac_nway_reset(struct net_device *netdev)
126{
127 struct phy_device *phydev = netdev->phydev;
128
129 if (!phydev)
130 return -ENODEV;
131
132 return genphy_restart_aneg(phydev);
133}
134
135static void emac_get_ringparam(struct net_device *netdev,
136 struct ethtool_ringparam *ring)
137{
138 struct emac_adapter *adpt = netdev_priv(netdev);
139
140 ring->rx_max_pending = EMAC_MAX_RX_DESCS;
141 ring->tx_max_pending = EMAC_MAX_TX_DESCS;
142 ring->rx_pending = adpt->rx_desc_cnt;
143 ring->tx_pending = adpt->tx_desc_cnt;
144}
145
038b9404
TT
146static int emac_set_ringparam(struct net_device *netdev,
147 struct ethtool_ringparam *ring)
148{
149 struct emac_adapter *adpt = netdev_priv(netdev);
150
151 /* We don't have separate queues/rings for small/large frames, so
152 * reject any attempt to specify those values separately.
153 */
154 if (ring->rx_mini_pending || ring->rx_jumbo_pending)
155 return -EINVAL;
156
157 adpt->tx_desc_cnt =
158 clamp_val(ring->tx_pending, EMAC_MIN_TX_DESCS, EMAC_MAX_TX_DESCS);
159
160 adpt->rx_desc_cnt =
161 clamp_val(ring->rx_pending, EMAC_MIN_RX_DESCS, EMAC_MAX_RX_DESCS);
162
163 if (netif_running(netdev))
164 return emac_reinit_locked(adpt);
165
166 return 0;
167}
168
79f664ed
TT
169static void emac_get_pauseparam(struct net_device *netdev,
170 struct ethtool_pauseparam *pause)
171{
b44700e9 172 struct emac_adapter *adpt = netdev_priv(netdev);
79f664ed 173
b44700e9
TT
174 pause->autoneg = adpt->automatic ? AUTONEG_ENABLE : AUTONEG_DISABLE;
175 pause->rx_pause = adpt->rx_flow_control ? 1 : 0;
3c19bd6c 176 pause->tx_pause = adpt->tx_flow_control ? 1 : 0;
b44700e9
TT
177}
178
179static int emac_set_pauseparam(struct net_device *netdev,
180 struct ethtool_pauseparam *pause)
181{
182 struct emac_adapter *adpt = netdev_priv(netdev);
183
184 adpt->automatic = pause->autoneg == AUTONEG_ENABLE;
185 adpt->rx_flow_control = pause->rx_pause != 0;
186 adpt->tx_flow_control = pause->tx_pause != 0;
187
188 if (netif_running(netdev))
189 return emac_reinit_locked(adpt);
190
191 return 0;
79f664ed
TT
192}
193
c4e7beea
TT
194/* Selected registers that might want to track during runtime. */
195static const u16 emac_regs[] = {
196 EMAC_DMA_MAS_CTRL,
197 EMAC_MAC_CTRL,
198 EMAC_TXQ_CTRL_0,
199 EMAC_RXQ_CTRL_0,
200 EMAC_DMA_CTRL,
201 EMAC_INT_MASK,
202 EMAC_AXI_MAST_CTRL,
203 EMAC_CORE_HW_VERSION,
204 EMAC_MISC_CTRL,
205};
206
207/* Every time emac_regs[] above is changed, increase this version number. */
208#define EMAC_REGS_VERSION 0
209
210#define EMAC_MAX_REG_SIZE ARRAY_SIZE(emac_regs)
211
212static void emac_get_regs(struct net_device *netdev,
213 struct ethtool_regs *regs, void *buff)
214{
215 struct emac_adapter *adpt = netdev_priv(netdev);
216 u32 *val = buff;
217 unsigned int i;
218
219 regs->version = EMAC_REGS_VERSION;
220 regs->len = EMAC_MAX_REG_SIZE * sizeof(u32);
221
222 for (i = 0; i < EMAC_MAX_REG_SIZE; i++)
223 val[i] = readl(adpt->base + emac_regs[i]);
224}
225
226static int emac_get_regs_len(struct net_device *netdev)
227{
2194bd10 228 return EMAC_MAX_REG_SIZE * sizeof(u32);
c4e7beea
TT
229}
230
4a7a3860
TT
231#define EMAC_PRIV_ENABLE_SINGLE_PAUSE BIT(0)
232
233static int emac_set_priv_flags(struct net_device *netdev, u32 flags)
234{
235 struct emac_adapter *adpt = netdev_priv(netdev);
236
237 adpt->single_pause_mode = !!(flags & EMAC_PRIV_ENABLE_SINGLE_PAUSE);
238
239 if (netif_running(netdev))
240 return emac_reinit_locked(adpt);
241
242 return 0;
243}
244
245static u32 emac_get_priv_flags(struct net_device *netdev)
246{
247 struct emac_adapter *adpt = netdev_priv(netdev);
248
249 return adpt->single_pause_mode ? EMAC_PRIV_ENABLE_SINGLE_PAUSE : 0;
250}
251
79f664ed
TT
252static const struct ethtool_ops emac_ethtool_ops = {
253 .get_link_ksettings = phy_ethtool_get_link_ksettings,
254 .set_link_ksettings = phy_ethtool_set_link_ksettings,
255
256 .get_msglevel = emac_get_msglevel,
257 .set_msglevel = emac_set_msglevel,
258
259 .get_sset_count = emac_get_sset_count,
260 .get_strings = emac_get_strings,
261 .get_ethtool_stats = emac_get_ethtool_stats,
262
263 .get_ringparam = emac_get_ringparam,
038b9404 264 .set_ringparam = emac_set_ringparam,
b44700e9 265
79f664ed 266 .get_pauseparam = emac_get_pauseparam,
b44700e9 267 .set_pauseparam = emac_set_pauseparam,
79f664ed
TT
268
269 .nway_reset = emac_nway_reset,
270
271 .get_link = ethtool_op_get_link,
c4e7beea
TT
272
273 .get_regs_len = emac_get_regs_len,
274 .get_regs = emac_get_regs,
4a7a3860
TT
275
276 .set_priv_flags = emac_set_priv_flags,
277 .get_priv_flags = emac_get_priv_flags,
79f664ed
TT
278};
279
280void emac_set_ethtool_ops(struct net_device *netdev)
281{
282 netdev->ethtool_ops = &emac_ethtool_ops;
283}