1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "mtk_eth_soc.h"
16
17static const char mtk_gdma_str[][ETH_GSTRING_LEN] = {
18#define _FE(x...) # x,
19MTK_STAT_REG_DECLARE
20#undef _FE
21};
22
23static int mtk_get_link_ksettings(struct net_device *dev,
24 struct ethtool_link_ksettings *cmd)
25{
26 struct mtk_mac *mac = netdev_priv(dev);
27 int err;
28
29 if (!mac->phy_dev)
30 return -ENODEV;
31
32 if (mac->phy_flags == MTK_PHY_FLAG_ATTACH) {
33 err = phy_read_status(mac->phy_dev);
34 if (err)
35 return -ENODEV;
36 }
37
38 phy_ethtool_ksettings_get(mac->phy_dev, cmd);
39 return 0;
40}
41
42static int mtk_set_link_ksettings(struct net_device *dev,
43 const struct ethtool_link_ksettings *cmd)
44{
45 struct mtk_mac *mac = netdev_priv(dev);
46
47 if (!mac->phy_dev)
48 return -ENODEV;
49
50 if (cmd->base.phy_address != mac->phy_dev->mdio.addr) {
51 if (mac->hw->phy->phy_node[cmd->base.phy_address]) {
52 mac->phy_dev = mac->hw->phy->phy[cmd->base.phy_address];
53 mac->phy_flags = MTK_PHY_FLAG_PORT;
54 } else if (mac->hw->mii_bus) {
55 mac->phy_dev = mdiobus_get_phy(mac->hw->mii_bus, cmd->base.phy_address);
56 if (!mac->phy_dev)
57 return -ENODEV;
58 mac->phy_flags = MTK_PHY_FLAG_ATTACH;
59 } else {
60 return -ENODEV;
61 }
62 }
63
64 return phy_ethtool_ksettings_set(mac->phy_dev, cmd);
65
66}
67
68static void mtk_get_drvinfo(struct net_device *dev,
69 struct ethtool_drvinfo *info)
70{
71 struct mtk_mac *mac = netdev_priv(dev);
72 struct mtk_soc_data *soc = mac->hw->soc;
73
74 strlcpy(info->driver, mac->hw->dev->driver->name, sizeof(info->driver));
75 strlcpy(info->bus_info, dev_name(mac->hw->dev), sizeof(info->bus_info));
76
77 if (soc->reg_table[MTK_REG_MTK_COUNTER_BASE])
78 info->n_stats = ARRAY_SIZE(mtk_gdma_str);
79}
80
81static u32 mtk_get_msglevel(struct net_device *dev)
82{
83 struct mtk_mac *mac = netdev_priv(dev);
84
85 return mac->hw->msg_enable;
86}
87
88static void mtk_set_msglevel(struct net_device *dev, u32 value)
89{
90 struct mtk_mac *mac = netdev_priv(dev);
91
92 mac->hw->msg_enable = value;
93}
94
95static int mtk_nway_reset(struct net_device *dev)
96{
97 struct mtk_mac *mac = netdev_priv(dev);
98
99 if (!mac->phy_dev)
100 return -EOPNOTSUPP;
101
102 return genphy_restart_aneg(mac->phy_dev);
103}
104
105static u32 mtk_get_link(struct net_device *dev)
106{
107 struct mtk_mac *mac = netdev_priv(dev);
108 int err;
109
110 if (!mac->phy_dev)
111 goto out_get_link;
112
113 if (mac->phy_flags == MTK_PHY_FLAG_ATTACH) {
114 err = genphy_update_link(mac->phy_dev);
115 if (err)
116 goto out_get_link;
117 }
118
119 return mac->phy_dev->link;
120
121out_get_link:
122 return ethtool_op_get_link(dev);
123}
124
125static int mtk_set_ringparam(struct net_device *dev,
126 struct ethtool_ringparam *ring)
127{
128 struct mtk_mac *mac = netdev_priv(dev);
129
130 if ((ring->tx_pending < 2) ||
131 (ring->rx_pending < 2) ||
132 (ring->rx_pending > mac->hw->soc->dma_ring_size) ||
133 (ring->tx_pending > mac->hw->soc->dma_ring_size))
134 return -EINVAL;
135
136 dev->netdev_ops->ndo_stop(dev);
137
138 mac->hw->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1);
139 mac->hw->rx_ring[0].rx_ring_size = BIT(fls(ring->rx_pending) - 1);
140
141 return dev->netdev_ops->ndo_open(dev);
142}
143
144static void mtk_get_ringparam(struct net_device *dev,
145 struct ethtool_ringparam *ring)
146{
147 struct mtk_mac *mac = netdev_priv(dev);
148
149 ring->rx_max_pending = mac->hw->soc->dma_ring_size;
150 ring->tx_max_pending = mac->hw->soc->dma_ring_size;
151 ring->rx_pending = mac->hw->rx_ring[0].rx_ring_size;
152 ring->tx_pending = mac->hw->tx_ring.tx_ring_size;
153}
154
155static void mtk_get_strings(struct net_device *dev, u32 stringset, u8 *data)
156{
157 switch (stringset) {
158 case ETH_SS_STATS:
159 memcpy(data, *mtk_gdma_str, sizeof(mtk_gdma_str));
160 break;
161 }
162}
163
164static int mtk_get_sset_count(struct net_device *dev, int sset)
165{
166 switch (sset) {
167 case ETH_SS_STATS:
168 return ARRAY_SIZE(mtk_gdma_str);
169 default:
170 return -EOPNOTSUPP;
171 }
172}
173
174static void mtk_get_ethtool_stats(struct net_device *dev,
175 struct ethtool_stats *stats, u64 *data)
176{
177 struct mtk_mac *mac = netdev_priv(dev);
178 struct mtk_hw_stats *hwstats = mac->hw_stats;
179 u64 *data_src, *data_dst;
180 unsigned int start;
181 int i;
182
183 if (netif_running(dev) && netif_device_present(dev)) {
184 if (spin_trylock(&hwstats->stats_lock)) {
185 mtk_stats_update_mac(mac);
186 spin_unlock(&hwstats->stats_lock);
187 }
188 }
189
190 do {
191 data_src = &hwstats->tx_bytes;
192 data_dst = data;
193 start = u64_stats_fetch_begin_irq(&hwstats->syncp);
194
195 for (i = 0; i < ARRAY_SIZE(mtk_gdma_str); i++)
196 *data_dst++ = *data_src++;
197
198 } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start));
199}
200
201static struct ethtool_ops mtk_ethtool_ops = {
202 .get_link_ksettings = mtk_get_link_ksettings,
203 .set_link_ksettings = mtk_set_link_ksettings,
204 .get_drvinfo = mtk_get_drvinfo,
205 .get_msglevel = mtk_get_msglevel,
206 .set_msglevel = mtk_set_msglevel,
207 .nway_reset = mtk_nway_reset,
208 .get_link = mtk_get_link,
209 .set_ringparam = mtk_set_ringparam,
210 .get_ringparam = mtk_get_ringparam,
211};
212
213void mtk_set_ethtool_ops(struct net_device *netdev)
214{
215 struct mtk_mac *mac = netdev_priv(netdev);
216 struct mtk_soc_data *soc = mac->hw->soc;
217
218 if (soc->reg_table[MTK_REG_MTK_COUNTER_BASE]) {
219 mtk_ethtool_ops.get_strings = mtk_get_strings;
220 mtk_ethtool_ops.get_sset_count = mtk_get_sset_count;
221 mtk_ethtool_ops.get_ethtool_stats = mtk_get_ethtool_stats;
222 }
223
224 netdev->ethtool_ops = &mtk_ethtool_ops;
225}
226