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
->device
->driver
->name
, sizeof(info
->driver
));
74 strlcpy(info
->version
, MTK_FE_DRV_VERSION
, sizeof(info
->version
));
75 strlcpy(info
->bus_info
, dev_name(priv
->device
), 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 static int fe_set_ringparam(struct net_device
*dev
,
129 struct ethtool_ringparam
*ring
)
131 struct fe_priv
*priv
= netdev_priv(dev
);
133 if ((ring
->tx_pending
< 2) ||
134 (ring
->rx_pending
< 2) ||
135 (ring
->rx_pending
> MAX_DMA_DESC
) ||
136 (ring
->tx_pending
> MAX_DMA_DESC
))
139 dev
->netdev_ops
->ndo_stop(dev
);
141 priv
->tx_ring
.tx_ring_size
= BIT(fls(ring
->tx_pending
) - 1);
142 priv
->rx_ring
.rx_ring_size
= BIT(fls(ring
->rx_pending
) - 1);
144 dev
->netdev_ops
->ndo_open(dev
);
149 static void fe_get_ringparam(struct net_device
*dev
,
150 struct ethtool_ringparam
*ring
)
152 struct fe_priv
*priv
= netdev_priv(dev
);
154 ring
->rx_max_pending
= MAX_DMA_DESC
;
155 ring
->tx_max_pending
= MAX_DMA_DESC
;
156 ring
->rx_pending
= priv
->rx_ring
.rx_ring_size
;
157 ring
->tx_pending
= priv
->tx_ring
.tx_ring_size
;
160 static void fe_get_strings(struct net_device
*dev
, u32 stringset
, u8
*data
)
164 memcpy(data
, *fe_gdma_str
, sizeof(fe_gdma_str
));
169 static int fe_get_sset_count(struct net_device
*dev
, int sset
)
173 return ARRAY_SIZE(fe_gdma_str
);
179 static void fe_get_ethtool_stats(struct net_device
*dev
,
180 struct ethtool_stats
*stats
, u64
*data
)
182 struct fe_priv
*priv
= netdev_priv(dev
);
183 struct fe_hw_stats
*hwstats
= priv
->hw_stats
;
184 u64
*data_src
, *data_dst
;
188 if (netif_running(dev
) && netif_device_present(dev
)) {
189 if (spin_trylock(&hwstats
->stats_lock
)) {
190 fe_stats_update(priv
);
191 spin_unlock(&hwstats
->stats_lock
);
196 data_src
= &hwstats
->tx_bytes
;
198 start
= u64_stats_fetch_begin_irq(&hwstats
->syncp
);
200 for (i
= 0; i
< ARRAY_SIZE(fe_gdma_str
); i
++)
201 *data_dst
++ = *data_src
++;
203 } while (u64_stats_fetch_retry_irq(&hwstats
->syncp
, start
));
206 static struct ethtool_ops fe_ethtool_ops
= {
207 .get_link_ksettings
= fe_get_link_ksettings
,
208 .set_link_ksettings
= fe_set_link_ksettings
,
209 .get_drvinfo
= fe_get_drvinfo
,
210 .get_msglevel
= fe_get_msglevel
,
211 .set_msglevel
= fe_set_msglevel
,
212 .nway_reset
= fe_nway_reset
,
213 .get_link
= fe_get_link
,
214 .set_ringparam
= fe_set_ringparam
,
215 .get_ringparam
= fe_get_ringparam
,
218 void fe_set_ethtool_ops(struct net_device
*netdev
)
220 struct fe_priv
*priv
= netdev_priv(netdev
);
221 struct fe_soc_data
*soc
= priv
->soc
;
223 if (soc
->reg_table
[FE_REG_FE_COUNTER_BASE
]) {
224 fe_ethtool_ops
.get_strings
= fe_get_strings
;
225 fe_ethtool_ops
.get_sset_count
= fe_get_sset_count
;
226 fe_ethtool_ops
.get_ethtool_stats
= fe_get_ethtool_stats
;
229 netdev
->ethtool_ops
= &fe_ethtool_ops
;