2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 * Copyright (C) 2009-2013 Michael Lee <igvtee@gmail.com>
18 #include "ralink_soc_eth.h"
20 static const char fe_gdma_str
[][ETH_GSTRING_LEN
] = {
21 #define _FE(x...) # x,
26 static int fe_get_settings(struct net_device
*dev
,
27 struct ethtool_cmd
*cmd
)
29 struct fe_priv
*priv
= netdev_priv(dev
);
35 if (priv
->phy_flags
== FE_PHY_FLAG_ATTACH
) {
36 err
= phy_read_status(priv
->phy_dev
);
41 return phy_ethtool_gset(priv
->phy_dev
, cmd
);
47 static int fe_set_settings(struct net_device
*dev
,
48 struct ethtool_cmd
*cmd
)
50 struct fe_priv
*priv
= netdev_priv(dev
);
55 if (cmd
->phy_address
!= priv
->phy_dev
->addr
) {
56 if (priv
->phy
->phy_node
[cmd
->phy_address
]) {
57 priv
->phy_dev
= priv
->phy
->phy
[cmd
->phy_address
];
58 priv
->phy_flags
= FE_PHY_FLAG_PORT
;
59 } else if (priv
->mii_bus
&&
60 priv
->mii_bus
->phy_map
[cmd
->phy_address
]) {
61 priv
->phy_dev
= priv
->mii_bus
->phy_map
[cmd
->phy_address
];
62 priv
->phy_flags
= FE_PHY_FLAG_ATTACH
;
67 return phy_ethtool_sset(priv
->phy_dev
, cmd
);
73 static void fe_get_drvinfo (struct net_device
*dev
,
74 struct ethtool_drvinfo
*info
)
76 struct fe_priv
*priv
= netdev_priv(dev
);
77 struct fe_soc_data
*soc
= priv
->soc
;
79 strlcpy(info
->driver
, priv
->device
->driver
->name
, sizeof(info
->driver
));
80 strlcpy(info
->version
, FE_DRV_VERSION
, sizeof(info
->version
));
81 strlcpy(info
->bus_info
, dev_name(priv
->device
), sizeof(info
->bus_info
));
83 if (soc
->reg_table
[FE_REG_FE_COUNTER_BASE
])
84 info
->n_stats
= ARRAY_SIZE(fe_gdma_str
);
87 static u32
fe_get_msglevel(struct net_device
*dev
)
89 struct fe_priv
*priv
= netdev_priv(dev
);
91 return priv
->msg_enable
;
94 static void fe_set_msglevel(struct net_device
*dev
, u32 value
)
96 struct fe_priv
*priv
= netdev_priv(dev
);
98 priv
->msg_enable
= value
;
101 static int fe_nway_reset(struct net_device
*dev
)
103 struct fe_priv
*priv
= netdev_priv(dev
);
108 return genphy_restart_aneg(priv
->phy_dev
);
114 static u32
fe_get_link(struct net_device
*dev
)
116 struct fe_priv
*priv
= netdev_priv(dev
);
122 if (priv
->phy_flags
== FE_PHY_FLAG_ATTACH
) {
123 err
= genphy_update_link(priv
->phy_dev
);
128 return priv
->phy_dev
->link
;
131 return ethtool_op_get_link(dev
);
134 static int fe_set_ringparam(struct net_device
*dev
,
135 struct ethtool_ringparam
*ring
)
137 struct fe_priv
*priv
= netdev_priv(dev
);
139 if ((ring
->tx_pending
< 2) ||
140 (ring
->rx_pending
< 2) ||
141 (ring
->rx_pending
> MAX_DMA_DESC
) ||
142 (ring
->tx_pending
> MAX_DMA_DESC
))
145 dev
->netdev_ops
->ndo_stop(dev
);
147 priv
->tx_ring
.tx_ring_size
= BIT(fls(ring
->tx_pending
) - 1);
148 priv
->rx_ring_size
= BIT(fls(ring
->rx_pending
) - 1);
150 dev
->netdev_ops
->ndo_open(dev
);
155 static void fe_get_ringparam(struct net_device
*dev
,
156 struct ethtool_ringparam
*ring
)
158 struct fe_priv
*priv
= netdev_priv(dev
);
160 ring
->rx_max_pending
= MAX_DMA_DESC
;
161 ring
->tx_max_pending
= MAX_DMA_DESC
;
162 ring
->rx_pending
= priv
->rx_ring_size
;
163 ring
->tx_pending
= priv
->tx_ring
.tx_ring_size
;
166 static void fe_get_strings(struct net_device
*dev
, u32 stringset
, u8
*data
)
170 memcpy(data
, *fe_gdma_str
, sizeof(fe_gdma_str
));
175 static int fe_get_sset_count(struct net_device
*dev
, int sset
)
179 return ARRAY_SIZE(fe_gdma_str
);
185 static void fe_get_ethtool_stats(struct net_device
*dev
,
186 struct ethtool_stats
*stats
, u64
*data
)
188 struct fe_priv
*priv
= netdev_priv(dev
);
189 struct fe_hw_stats
*hwstats
= priv
->hw_stats
;
190 u64
*data_src
, *data_dst
;
194 if (netif_running(dev
) && netif_device_present(dev
)) {
195 if (spin_trylock(&hwstats
->stats_lock
)) {
196 fe_stats_update(priv
);
197 spin_unlock(&hwstats
->stats_lock
);
202 data_src
= &hwstats
->tx_bytes
;
204 start
= u64_stats_fetch_begin_irq(&hwstats
->syncp
);
206 for (i
= 0; i
< ARRAY_SIZE(fe_gdma_str
); i
++)
207 *data_dst
++ = *data_src
++;
209 } while (u64_stats_fetch_retry_irq(&hwstats
->syncp
, start
));
212 static struct ethtool_ops fe_ethtool_ops
= {
213 .get_settings
= fe_get_settings
,
214 .set_settings
= fe_set_settings
,
215 .get_drvinfo
= fe_get_drvinfo
,
216 .get_msglevel
= fe_get_msglevel
,
217 .set_msglevel
= fe_set_msglevel
,
218 .nway_reset
= fe_nway_reset
,
219 .get_link
= fe_get_link
,
220 .set_ringparam
= fe_set_ringparam
,
221 .get_ringparam
= fe_get_ringparam
,
224 void fe_set_ethtool_ops(struct net_device
*netdev
)
226 struct fe_priv
*priv
= netdev_priv(netdev
);
227 struct fe_soc_data
*soc
= priv
->soc
;
229 if (soc
->reg_table
[FE_REG_FE_COUNTER_BASE
]) {
230 fe_ethtool_ops
.get_strings
= fe_get_strings
;
231 fe_ethtool_ops
.get_sset_count
= fe_get_sset_count
;
232 fe_ethtool_ops
.get_ethtool_stats
= fe_get_ethtool_stats
;
235 netdev
->ethtool_ops
= &fe_ethtool_ops
;