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
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.
10 * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
11 * Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
12 * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
15 #include "mtk_eth_soc.h"
19 char name
[ETH_GSTRING_LEN
];
23 #define MTK_HW_STAT(stat) { \
25 .idx = offsetof(struct mtk_hw_stats, stat) / sizeof(u64) \
28 static const struct mtk_stat mtk_ethtool_hw_stats
[] = {
29 MTK_HW_STAT(tx_bytes
),
30 MTK_HW_STAT(tx_packets
),
32 MTK_HW_STAT(tx_collisions
),
33 MTK_HW_STAT(rx_bytes
),
34 MTK_HW_STAT(rx_packets
),
35 MTK_HW_STAT(rx_overflow
),
36 MTK_HW_STAT(rx_fcs_errors
),
37 MTK_HW_STAT(rx_short_errors
),
38 MTK_HW_STAT(rx_long_errors
),
39 MTK_HW_STAT(rx_checksum_errors
),
40 MTK_HW_STAT(rx_flow_control_packets
),
43 #define MTK_HW_STATS_LEN ARRAY_SIZE(mtk_ethtool_hw_stats)
45 static int mtk_get_link_ksettings(struct net_device
*dev
,
46 struct ethtool_link_ksettings
*cmd
)
48 struct mtk_mac
*mac
= netdev_priv(dev
);
54 if (mac
->phy_flags
== MTK_PHY_FLAG_ATTACH
) {
55 err
= phy_read_status(mac
->phy_dev
);
60 phy_ethtool_ksettings_get(mac
->phy_dev
, cmd
);
64 static int mtk_set_link_ksettings(struct net_device
*dev
,
65 const struct ethtool_link_ksettings
*cmd
)
67 struct mtk_mac
*mac
= netdev_priv(dev
);
72 if (cmd
->base
.phy_address
!= mac
->phy_dev
->mdio
.addr
) {
73 if (mac
->hw
->phy
->phy_node
[cmd
->base
.phy_address
]) {
74 mac
->phy_dev
= mac
->hw
->phy
->phy
[cmd
->base
.phy_address
];
75 mac
->phy_flags
= MTK_PHY_FLAG_PORT
;
76 } else if (mac
->hw
->mii_bus
) {
77 mac
->phy_dev
= mdiobus_get_phy(mac
->hw
->mii_bus
,
78 cmd
->base
.phy_address
);
81 mac
->phy_flags
= MTK_PHY_FLAG_ATTACH
;
87 return phy_ethtool_ksettings_set(mac
->phy_dev
, cmd
);
90 static void mtk_get_drvinfo(struct net_device
*dev
,
91 struct ethtool_drvinfo
*info
)
93 struct mtk_mac
*mac
= netdev_priv(dev
);
94 struct mtk_soc_data
*soc
= mac
->hw
->soc
;
96 strlcpy(info
->driver
, mac
->hw
->dev
->driver
->name
, sizeof(info
->driver
));
97 strlcpy(info
->bus_info
, dev_name(mac
->hw
->dev
), sizeof(info
->bus_info
));
99 if (soc
->reg_table
[MTK_REG_MTK_COUNTER_BASE
])
100 info
->n_stats
= MTK_HW_STATS_LEN
;
103 static u32
mtk_get_msglevel(struct net_device
*dev
)
105 struct mtk_mac
*mac
= netdev_priv(dev
);
107 return mac
->hw
->msg_enable
;
110 static void mtk_set_msglevel(struct net_device
*dev
, u32 value
)
112 struct mtk_mac
*mac
= netdev_priv(dev
);
114 mac
->hw
->msg_enable
= value
;
117 static int mtk_nway_reset(struct net_device
*dev
)
119 struct mtk_mac
*mac
= netdev_priv(dev
);
124 return genphy_restart_aneg(mac
->phy_dev
);
127 static u32
mtk_get_link(struct net_device
*dev
)
129 struct mtk_mac
*mac
= netdev_priv(dev
);
135 if (mac
->phy_flags
== MTK_PHY_FLAG_ATTACH
) {
136 err
= genphy_update_link(mac
->phy_dev
);
141 return mac
->phy_dev
->link
;
144 return ethtool_op_get_link(dev
);
147 static int mtk_set_ringparam(struct net_device
*dev
,
148 struct ethtool_ringparam
*ring
)
150 struct mtk_mac
*mac
= netdev_priv(dev
);
152 if ((ring
->tx_pending
< 2) ||
153 (ring
->rx_pending
< 2) ||
154 (ring
->rx_pending
> mac
->hw
->soc
->dma_ring_size
) ||
155 (ring
->tx_pending
> mac
->hw
->soc
->dma_ring_size
))
158 dev
->netdev_ops
->ndo_stop(dev
);
160 mac
->hw
->tx_ring
.tx_ring_size
= BIT(fls(ring
->tx_pending
) - 1);
161 mac
->hw
->rx_ring
[0].rx_ring_size
= BIT(fls(ring
->rx_pending
) - 1);
163 return dev
->netdev_ops
->ndo_open(dev
);
166 static void mtk_get_ringparam(struct net_device
*dev
,
167 struct ethtool_ringparam
*ring
)
169 struct mtk_mac
*mac
= netdev_priv(dev
);
171 ring
->rx_max_pending
= mac
->hw
->soc
->dma_ring_size
;
172 ring
->tx_max_pending
= mac
->hw
->soc
->dma_ring_size
;
173 ring
->rx_pending
= mac
->hw
->rx_ring
[0].rx_ring_size
;
174 ring
->tx_pending
= mac
->hw
->tx_ring
.tx_ring_size
;
177 static void mtk_get_strings(struct net_device
*dev
, u32 stringset
, u8
*data
)
183 for (i
= 0; i
< MTK_HW_STATS_LEN
; i
++) {
184 memcpy(data
, mtk_ethtool_hw_stats
[i
].name
,
186 data
+= ETH_GSTRING_LEN
;
192 static int mtk_get_sset_count(struct net_device
*dev
, int sset
)
196 return MTK_HW_STATS_LEN
;
202 static void mtk_get_ethtool_stats(struct net_device
*dev
,
203 struct ethtool_stats
*stats
, u64
*data
)
205 struct mtk_mac
*mac
= netdev_priv(dev
);
206 struct mtk_hw_stats
*hwstats
= mac
->hw_stats
;
210 if (netif_running(dev
) && netif_device_present(dev
)) {
211 if (spin_trylock(&hwstats
->stats_lock
)) {
212 mtk_stats_update_mac(mac
);
213 spin_unlock(&hwstats
->stats_lock
);
218 start
= u64_stats_fetch_begin_irq(&hwstats
->syncp
);
219 for (i
= 0; i
< MTK_HW_STATS_LEN
; i
++)
220 data
[i
] = ((u64
*)hwstats
)[mtk_ethtool_hw_stats
[i
].idx
];
222 } while (u64_stats_fetch_retry_irq(&hwstats
->syncp
, start
));
225 static struct ethtool_ops mtk_ethtool_ops
= {
226 .get_link_ksettings
= mtk_get_link_ksettings
,
227 .set_link_ksettings
= mtk_set_link_ksettings
,
228 .get_drvinfo
= mtk_get_drvinfo
,
229 .get_msglevel
= mtk_get_msglevel
,
230 .set_msglevel
= mtk_set_msglevel
,
231 .nway_reset
= mtk_nway_reset
,
232 .get_link
= mtk_get_link
,
233 .set_ringparam
= mtk_set_ringparam
,
234 .get_ringparam
= mtk_get_ringparam
,
237 void mtk_set_ethtool_ops(struct net_device
*netdev
)
239 struct mtk_mac
*mac
= netdev_priv(netdev
);
240 struct mtk_soc_data
*soc
= mac
->hw
->soc
;
242 if (soc
->reg_table
[MTK_REG_MTK_COUNTER_BASE
]) {
243 mtk_ethtool_ops
.get_strings
= mtk_get_strings
;
244 mtk_ethtool_ops
.get_sset_count
= mtk_get_sset_count
;
245 mtk_ethtool_ops
.get_ethtool_stats
= mtk_get_ethtool_stats
;
248 netdev
->ethtool_ops
= &mtk_ethtool_ops
;