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)
92 return EMAC_STATS_LEN;
98 static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
104 for (i = 0; i < EMAC_STATS_LEN; i++) {
105 strlcpy(data, emac_ethtool_stat_strings[i],
107 data += ETH_GSTRING_LEN;
113 static void emac_get_ethtool_stats(struct net_device *netdev,
114 struct ethtool_stats *stats,
117 struct emac_adapter *adpt = netdev_priv(netdev);
119 spin_lock(&adpt->stats.lock);
121 emac_update_hw_stats(adpt);
122 memcpy(data, &adpt->stats, EMAC_STATS_LEN * sizeof(u64));
124 spin_unlock(&adpt->stats.lock);
127 static int emac_nway_reset(struct net_device *netdev)
129 struct phy_device *phydev = netdev->phydev;
134 return genphy_restart_aneg(phydev);
137 static void emac_get_ringparam(struct net_device *netdev,
138 struct ethtool_ringparam *ring)
140 struct emac_adapter *adpt = netdev_priv(netdev);
142 ring->rx_max_pending = EMAC_MAX_RX_DESCS;
143 ring->tx_max_pending = EMAC_MAX_TX_DESCS;
144 ring->rx_pending = adpt->rx_desc_cnt;
145 ring->tx_pending = adpt->tx_desc_cnt;
148 static int emac_set_ringparam(struct net_device *netdev,
149 struct ethtool_ringparam *ring)
151 struct emac_adapter *adpt = netdev_priv(netdev);
153 /* We don't have separate queues/rings for small/large frames, so
154 * reject any attempt to specify those values separately.
156 if (ring->rx_mini_pending || ring->rx_jumbo_pending)
160 clamp_val(ring->tx_pending, EMAC_MIN_TX_DESCS, EMAC_MAX_TX_DESCS);
163 clamp_val(ring->rx_pending, EMAC_MIN_RX_DESCS, EMAC_MAX_RX_DESCS);
165 if (netif_running(netdev))
166 return emac_reinit_locked(adpt);
171 static void emac_get_pauseparam(struct net_device *netdev,
172 struct ethtool_pauseparam *pause)
174 struct emac_adapter *adpt = netdev_priv(netdev);
176 pause->autoneg = adpt->automatic ? AUTONEG_ENABLE : AUTONEG_DISABLE;
177 pause->rx_pause = adpt->rx_flow_control ? 1 : 0;
178 pause->tx_pause = adpt->tx_flow_control ? 1 : 0;
181 static int emac_set_pauseparam(struct net_device *netdev,
182 struct ethtool_pauseparam *pause)
184 struct emac_adapter *adpt = netdev_priv(netdev);
186 adpt->automatic = pause->autoneg == AUTONEG_ENABLE;
187 adpt->rx_flow_control = pause->rx_pause != 0;
188 adpt->tx_flow_control = pause->tx_pause != 0;
190 if (netif_running(netdev))
191 return emac_reinit_locked(adpt);
196 /* Selected registers that might want to track during runtime. */
197 static const u16 emac_regs[] = {
205 EMAC_CORE_HW_VERSION,
209 /* Every time emac_regs[] above is changed, increase this version number. */
210 #define EMAC_REGS_VERSION 0
212 #define EMAC_MAX_REG_SIZE ARRAY_SIZE(emac_regs)
214 static void emac_get_regs(struct net_device *netdev,
215 struct ethtool_regs *regs, void *buff)
217 struct emac_adapter *adpt = netdev_priv(netdev);
221 regs->version = EMAC_REGS_VERSION;
222 regs->len = EMAC_MAX_REG_SIZE * sizeof(u32);
224 for (i = 0; i < EMAC_MAX_REG_SIZE; i++)
225 val[i] = readl(adpt->base + emac_regs[i]);
228 static int emac_get_regs_len(struct net_device *netdev)
230 return EMAC_MAX_REG_SIZE * sizeof(u32);
233 static const struct ethtool_ops emac_ethtool_ops = {
234 .get_link_ksettings = phy_ethtool_get_link_ksettings,
235 .set_link_ksettings = phy_ethtool_set_link_ksettings,
237 .get_msglevel = emac_get_msglevel,
238 .set_msglevel = emac_set_msglevel,
240 .get_sset_count = emac_get_sset_count,
241 .get_strings = emac_get_strings,
242 .get_ethtool_stats = emac_get_ethtool_stats,
244 .get_ringparam = emac_get_ringparam,
245 .set_ringparam = emac_set_ringparam,
247 .get_pauseparam = emac_get_pauseparam,
248 .set_pauseparam = emac_set_pauseparam,
250 .nway_reset = emac_nway_reset,
252 .get_link = ethtool_op_get_link,
254 .get_regs_len = emac_get_regs_len,
255 .get_regs = emac_get_regs,
258 void emac_set_ethtool_ops(struct net_device *netdev)
260 netdev->ethtool_ops = &emac_ethtool_ops;