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-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>
15 #include "mtk_eth_soc.h"
17 static const char fe_gdma_str
[][ETH_GSTRING_LEN
] = {
18 #define _FE(x...) # x,
23 static int fe_get_link_ksettings(struct net_device
*ndev
,
24 struct ethtool_link_ksettings
*cmd
)
26 struct fe_priv
*priv
= netdev_priv(ndev
);
31 if (priv
->phy_flags
== FE_PHY_FLAG_ATTACH
) {
32 if (phy_read_status(priv
->phy_dev
))
36 phy_ethtool_ksettings_get(ndev
->phydev
, cmd
);
41 static int fe_set_link_ksettings(struct net_device
*ndev
,
42 const struct ethtool_link_ksettings
*cmd
)
44 struct fe_priv
*priv
= netdev_priv(ndev
);
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
;
61 return phy_ethtool_ksettings_set(ndev
->phydev
, cmd
);
67 static void fe_get_drvinfo(struct net_device
*dev
,
68 struct ethtool_drvinfo
*info
)
70 struct fe_priv
*priv
= netdev_priv(dev
);
71 struct fe_soc_data
*soc
= priv
->soc
;
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
));
77 if (soc
->reg_table
[FE_REG_FE_COUNTER_BASE
])
78 info
->n_stats
= ARRAY_SIZE(fe_gdma_str
);
81 static u32
fe_get_msglevel(struct net_device
*dev
)
83 struct fe_priv
*priv
= netdev_priv(dev
);
85 return priv
->msg_enable
;
88 static void fe_set_msglevel(struct net_device
*dev
, u32 value
)
90 struct fe_priv
*priv
= netdev_priv(dev
);
92 priv
->msg_enable
= value
;
95 static int fe_nway_reset(struct net_device
*dev
)
97 struct fe_priv
*priv
= netdev_priv(dev
);
102 return genphy_restart_aneg(priv
->phy_dev
);
108 static u32
fe_get_link(struct net_device
*dev
)
110 struct fe_priv
*priv
= netdev_priv(dev
);
116 if (priv
->phy_flags
== FE_PHY_FLAG_ATTACH
) {
117 err
= genphy_update_link(priv
->phy_dev
);
122 return priv
->phy_dev
->link
;
125 return ethtool_op_get_link(dev
);
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
)
134 static int fe_set_ringparam(struct net_device
*dev
,
135 struct ethtool_ringparam
*ring
)
138 struct fe_priv
*priv
= netdev_priv(dev
);
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
))
146 dev
->netdev_ops
->ndo_stop(dev
);
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);
151 dev
->netdev_ops
->ndo_open(dev
);
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
)
162 static void fe_get_ringparam(struct net_device
*dev
,
163 struct ethtool_ringparam
*ring
)
166 struct fe_priv
*priv
= netdev_priv(dev
);
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
;
174 static void fe_get_strings(struct net_device
*dev
, u32 stringset
, u8
*data
)
178 ethtool_puts(&data
, *fe_gdma_str
);
183 static int fe_get_sset_count(struct net_device
*dev
, int sset
)
187 return ARRAY_SIZE(fe_gdma_str
);
193 static void fe_get_ethtool_stats(struct net_device
*dev
,
194 struct ethtool_stats
*stats
, u64
*data
)
196 struct fe_priv
*priv
= netdev_priv(dev
);
197 struct fe_hw_stats
*hwstats
= priv
->hw_stats
;
198 u64
*data_src
, *data_dst
;
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
);
210 data_src
= &hwstats
->tx_bytes
;
212 start
= u64_stats_fetch_begin_irq(&hwstats
->syncp
);
214 for (i
= 0; i
< ARRAY_SIZE(fe_gdma_str
); i
++)
215 *data_dst
++ = *data_src
++;
217 } while (u64_stats_fetch_retry_irq(&hwstats
->syncp
, start
));
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
,
232 void fe_set_ethtool_ops(struct net_device
*netdev
)
234 struct fe_priv
*priv
= netdev_priv(netdev
);
235 struct fe_soc_data
*soc
= priv
->soc
;
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
;
243 netdev
->ethtool_ops
= &fe_ethtool_ops
;