ramips: 6.1: ralink: fix ethernet driver with 6.1
[openwrt/staging/wigyori.git] / target / linux / ramips / files / drivers / net / ethernet / ralink / ethtool.c
1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License
4 *
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
9 *
10 * Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
11 * Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name>
12 * Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
13 */
14
15 #include "mtk_eth_soc.h"
16
17 static const char fe_gdma_str[][ETH_GSTRING_LEN] = {
18 #define _FE(x...) # x,
19 FE_STAT_REG_DECLARE
20 #undef _FE
21 };
22
23 static int fe_get_link_ksettings(struct net_device *ndev,
24 struct ethtool_link_ksettings *cmd)
25 {
26 struct fe_priv *priv = netdev_priv(ndev);
27
28 if (!priv->phy_dev)
29 return -ENODEV;
30
31 if (priv->phy_flags == FE_PHY_FLAG_ATTACH) {
32 if (phy_read_status(priv->phy_dev))
33 return -ENODEV;
34 }
35
36 phy_ethtool_ksettings_get(ndev->phydev, cmd);
37
38 return 0;
39 }
40
41 static int fe_set_link_ksettings(struct net_device *ndev,
42 const struct ethtool_link_ksettings *cmd)
43 {
44 struct fe_priv *priv = netdev_priv(ndev);
45
46 if (!priv->phy_dev)
47 goto out_sset;
48
49 if (cmd->base.phy_address != priv->phy_dev->mdio.addr) {
50 if (priv->phy->phy_node[cmd->base.phy_address]) {
51 priv->phy_dev = priv->phy->phy[cmd->base.phy_address];
52 priv->phy_flags = FE_PHY_FLAG_PORT;
53 } else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, cmd->base.phy_address)) {
54 priv->phy_dev = mdiobus_get_phy(priv->mii_bus, cmd->base.phy_address);
55 priv->phy_flags = FE_PHY_FLAG_ATTACH;
56 } else {
57 goto out_sset;
58 }
59 }
60
61 return phy_ethtool_ksettings_set(ndev->phydev, cmd);
62
63 out_sset:
64 return -ENODEV;
65 }
66
67 static void fe_get_drvinfo(struct net_device *dev,
68 struct ethtool_drvinfo *info)
69 {
70 struct fe_priv *priv = netdev_priv(dev);
71 struct fe_soc_data *soc = priv->soc;
72
73 strlcpy(info->driver, priv->dev->driver->name, sizeof(info->driver));
74 strlcpy(info->version, MTK_FE_DRV_VERSION, sizeof(info->version));
75 strlcpy(info->bus_info, dev_name(priv->dev), sizeof(info->bus_info));
76
77 if (soc->reg_table[FE_REG_FE_COUNTER_BASE])
78 info->n_stats = ARRAY_SIZE(fe_gdma_str);
79 }
80
81 static u32 fe_get_msglevel(struct net_device *dev)
82 {
83 struct fe_priv *priv = netdev_priv(dev);
84
85 return priv->msg_enable;
86 }
87
88 static void fe_set_msglevel(struct net_device *dev, u32 value)
89 {
90 struct fe_priv *priv = netdev_priv(dev);
91
92 priv->msg_enable = value;
93 }
94
95 static int fe_nway_reset(struct net_device *dev)
96 {
97 struct fe_priv *priv = netdev_priv(dev);
98
99 if (!priv->phy_dev)
100 goto out_nway_reset;
101
102 return genphy_restart_aneg(priv->phy_dev);
103
104 out_nway_reset:
105 return -EOPNOTSUPP;
106 }
107
108 static u32 fe_get_link(struct net_device *dev)
109 {
110 struct fe_priv *priv = netdev_priv(dev);
111 int err;
112
113 if (!priv->phy_dev)
114 goto out_get_link;
115
116 if (priv->phy_flags == FE_PHY_FLAG_ATTACH) {
117 err = genphy_update_link(priv->phy_dev);
118 if (err)
119 goto out_get_link;
120 }
121
122 return priv->phy_dev->link;
123
124 out_get_link:
125 return ethtool_op_get_link(dev);
126 }
127
128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
129 static int fe_set_ringparam(struct net_device *dev,
130 struct ethtool_ringparam *ring,
131 struct kernel_ethtool_ringparam *kernel_rp,
132 struct netlink_ext_ack *extack)
133 #else
134 static int fe_set_ringparam(struct net_device *dev,
135 struct ethtool_ringparam *ring)
136 #endif
137 {
138 struct fe_priv *priv = netdev_priv(dev);
139
140 if ((ring->tx_pending < 2) ||
141 (ring->rx_pending < 2) ||
142 (ring->rx_pending > MAX_DMA_DESC) ||
143 (ring->tx_pending > MAX_DMA_DESC))
144 return -EINVAL;
145
146 dev->netdev_ops->ndo_stop(dev);
147
148 priv->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1);
149 priv->rx_ring.rx_ring_size = BIT(fls(ring->rx_pending) - 1);
150
151 dev->netdev_ops->ndo_open(dev);
152
153 return 0;
154 }
155
156 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
157 static void fe_get_ringparam(struct net_device *dev,
158 struct ethtool_ringparam *ring,
159 struct kernel_ethtool_ringparam *kernel_rp,
160 struct netlink_ext_ack *extack)
161 #else
162 static void fe_get_ringparam(struct net_device *dev,
163 struct ethtool_ringparam *ring)
164 #endif
165 {
166 struct fe_priv *priv = netdev_priv(dev);
167
168 ring->rx_max_pending = MAX_DMA_DESC;
169 ring->tx_max_pending = MAX_DMA_DESC;
170 ring->rx_pending = priv->rx_ring.rx_ring_size;
171 ring->tx_pending = priv->tx_ring.tx_ring_size;
172 }
173
174 static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data)
175 {
176 switch (stringset) {
177 case ETH_SS_STATS:
178 ethtool_puts(&data, *fe_gdma_str);
179 break;
180 }
181 }
182
183 static int fe_get_sset_count(struct net_device *dev, int sset)
184 {
185 switch (sset) {
186 case ETH_SS_STATS:
187 return ARRAY_SIZE(fe_gdma_str);
188 default:
189 return -EOPNOTSUPP;
190 }
191 }
192
193 static void fe_get_ethtool_stats(struct net_device *dev,
194 struct ethtool_stats *stats, u64 *data)
195 {
196 struct fe_priv *priv = netdev_priv(dev);
197 struct fe_hw_stats *hwstats = priv->hw_stats;
198 u64 *data_src, *data_dst;
199 unsigned int start;
200 int i;
201
202 if (netif_running(dev) && netif_device_present(dev)) {
203 if (spin_trylock(&hwstats->stats_lock)) {
204 fe_stats_update(priv);
205 spin_unlock(&hwstats->stats_lock);
206 }
207 }
208
209 do {
210 data_src = &hwstats->tx_bytes;
211 data_dst = data;
212 start = u64_stats_fetch_begin_irq(&hwstats->syncp);
213
214 for (i = 0; i < ARRAY_SIZE(fe_gdma_str); i++)
215 *data_dst++ = *data_src++;
216
217 } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start));
218 }
219
220 static struct ethtool_ops fe_ethtool_ops = {
221 .get_link_ksettings = fe_get_link_ksettings,
222 .set_link_ksettings = fe_set_link_ksettings,
223 .get_drvinfo = fe_get_drvinfo,
224 .get_msglevel = fe_get_msglevel,
225 .set_msglevel = fe_set_msglevel,
226 .nway_reset = fe_nway_reset,
227 .get_link = fe_get_link,
228 .set_ringparam = fe_set_ringparam,
229 .get_ringparam = fe_get_ringparam,
230 };
231
232 void fe_set_ethtool_ops(struct net_device *netdev)
233 {
234 struct fe_priv *priv = netdev_priv(netdev);
235 struct fe_soc_data *soc = priv->soc;
236
237 if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) {
238 fe_ethtool_ops.get_strings = fe_get_strings;
239 fe_ethtool_ops.get_sset_count = fe_get_sset_count;
240 fe_ethtool_ops.get_ethtool_stats = fe_get_ethtool_stats;
241 }
242
243 netdev->ethtool_ops = &fe_ethtool_ops;
244 }