1 /* Copyright (c) 2016, The Linux Foundation. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
13 #include <linux/ethtool.h>
14 #include <linux/phy.h>
18 static const char * const emac_ethtool_stat_strings
[] = {
72 #define EMAC_STATS_LEN ARRAY_SIZE(emac_ethtool_stat_strings)
74 static u32
emac_get_msglevel(struct net_device
*netdev
)
76 struct emac_adapter
*adpt
= netdev_priv(netdev
);
78 return adpt
->msg_enable
;
81 static void emac_set_msglevel(struct net_device
*netdev
, u32 data
)
83 struct emac_adapter
*adpt
= netdev_priv(netdev
);
85 adpt
->msg_enable
= data
;
88 static int emac_get_sset_count(struct net_device
*netdev
, int sset
)
91 case ETH_SS_PRIV_FLAGS
:
94 return EMAC_STATS_LEN
;
100 static void emac_get_strings(struct net_device
*netdev
, u32 stringset
, u8
*data
)
105 case ETH_SS_PRIV_FLAGS
:
106 strcpy(data
, "single-pause-mode");
110 for (i
= 0; i
< EMAC_STATS_LEN
; i
++) {
111 strlcpy(data
, emac_ethtool_stat_strings
[i
],
113 data
+= ETH_GSTRING_LEN
;
119 static void emac_get_ethtool_stats(struct net_device
*netdev
,
120 struct ethtool_stats
*stats
,
123 struct emac_adapter
*adpt
= netdev_priv(netdev
);
125 spin_lock(&adpt
->stats
.lock
);
127 emac_update_hw_stats(adpt
);
128 memcpy(data
, &adpt
->stats
, EMAC_STATS_LEN
* sizeof(u64
));
130 spin_unlock(&adpt
->stats
.lock
);
133 static int emac_nway_reset(struct net_device
*netdev
)
135 struct phy_device
*phydev
= netdev
->phydev
;
140 return genphy_restart_aneg(phydev
);
143 static void emac_get_ringparam(struct net_device
*netdev
,
144 struct ethtool_ringparam
*ring
)
146 struct emac_adapter
*adpt
= netdev_priv(netdev
);
148 ring
->rx_max_pending
= EMAC_MAX_RX_DESCS
;
149 ring
->tx_max_pending
= EMAC_MAX_TX_DESCS
;
150 ring
->rx_pending
= adpt
->rx_desc_cnt
;
151 ring
->tx_pending
= adpt
->tx_desc_cnt
;
154 static int emac_set_ringparam(struct net_device
*netdev
,
155 struct ethtool_ringparam
*ring
)
157 struct emac_adapter
*adpt
= netdev_priv(netdev
);
159 /* We don't have separate queues/rings for small/large frames, so
160 * reject any attempt to specify those values separately.
162 if (ring
->rx_mini_pending
|| ring
->rx_jumbo_pending
)
166 clamp_val(ring
->tx_pending
, EMAC_MIN_TX_DESCS
, EMAC_MAX_TX_DESCS
);
169 clamp_val(ring
->rx_pending
, EMAC_MIN_RX_DESCS
, EMAC_MAX_RX_DESCS
);
171 if (netif_running(netdev
))
172 return emac_reinit_locked(adpt
);
177 static void emac_get_pauseparam(struct net_device
*netdev
,
178 struct ethtool_pauseparam
*pause
)
180 struct emac_adapter
*adpt
= netdev_priv(netdev
);
182 pause
->autoneg
= adpt
->automatic
? AUTONEG_ENABLE
: AUTONEG_DISABLE
;
183 pause
->rx_pause
= adpt
->rx_flow_control
? 1 : 0;
184 pause
->tx_pause
= adpt
->tx_flow_control
? 1 : 0;
187 static int emac_set_pauseparam(struct net_device
*netdev
,
188 struct ethtool_pauseparam
*pause
)
190 struct emac_adapter
*adpt
= netdev_priv(netdev
);
192 adpt
->automatic
= pause
->autoneg
== AUTONEG_ENABLE
;
193 adpt
->rx_flow_control
= pause
->rx_pause
!= 0;
194 adpt
->tx_flow_control
= pause
->tx_pause
!= 0;
196 if (netif_running(netdev
))
197 return emac_reinit_locked(adpt
);
202 /* Selected registers that might want to track during runtime. */
203 static const u16 emac_regs
[] = {
211 EMAC_CORE_HW_VERSION
,
215 /* Every time emac_regs[] above is changed, increase this version number. */
216 #define EMAC_REGS_VERSION 0
218 #define EMAC_MAX_REG_SIZE ARRAY_SIZE(emac_regs)
220 static void emac_get_regs(struct net_device
*netdev
,
221 struct ethtool_regs
*regs
, void *buff
)
223 struct emac_adapter
*adpt
= netdev_priv(netdev
);
227 regs
->version
= EMAC_REGS_VERSION
;
228 regs
->len
= EMAC_MAX_REG_SIZE
* sizeof(u32
);
230 for (i
= 0; i
< EMAC_MAX_REG_SIZE
; i
++)
231 val
[i
] = readl(adpt
->base
+ emac_regs
[i
]);
234 static int emac_get_regs_len(struct net_device
*netdev
)
236 return EMAC_MAX_REG_SIZE
* sizeof(u32
);
239 #define EMAC_PRIV_ENABLE_SINGLE_PAUSE BIT(0)
241 static int emac_set_priv_flags(struct net_device
*netdev
, u32 flags
)
243 struct emac_adapter
*adpt
= netdev_priv(netdev
);
245 adpt
->single_pause_mode
= !!(flags
& EMAC_PRIV_ENABLE_SINGLE_PAUSE
);
247 if (netif_running(netdev
))
248 return emac_reinit_locked(adpt
);
253 static u32
emac_get_priv_flags(struct net_device
*netdev
)
255 struct emac_adapter
*adpt
= netdev_priv(netdev
);
257 return adpt
->single_pause_mode
? EMAC_PRIV_ENABLE_SINGLE_PAUSE
: 0;
260 static const struct ethtool_ops emac_ethtool_ops
= {
261 .get_link_ksettings
= phy_ethtool_get_link_ksettings
,
262 .set_link_ksettings
= phy_ethtool_set_link_ksettings
,
264 .get_msglevel
= emac_get_msglevel
,
265 .set_msglevel
= emac_set_msglevel
,
267 .get_sset_count
= emac_get_sset_count
,
268 .get_strings
= emac_get_strings
,
269 .get_ethtool_stats
= emac_get_ethtool_stats
,
271 .get_ringparam
= emac_get_ringparam
,
272 .set_ringparam
= emac_set_ringparam
,
274 .get_pauseparam
= emac_get_pauseparam
,
275 .set_pauseparam
= emac_set_pauseparam
,
277 .nway_reset
= emac_nway_reset
,
279 .get_link
= ethtool_op_get_link
,
281 .get_regs_len
= emac_get_regs_len
,
282 .get_regs
= emac_get_regs
,
284 .set_priv_flags
= emac_set_priv_flags
,
285 .get_priv_flags
= emac_get_priv_flags
,
288 void emac_set_ethtool_ops(struct net_device
*netdev
)
290 netdev
->ethtool_ops
= &emac_ethtool_ops
;