Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2016, The Linux Foundation. All rights reserved.
0003  */
0004 
0005 #include <linux/ethtool.h>
0006 #include <linux/phy.h>
0007 
0008 #include "emac.h"
0009 
0010 static const char * const emac_ethtool_stat_strings[] = {
0011     "rx_ok",
0012     "rx_bcast",
0013     "rx_mcast",
0014     "rx_pause",
0015     "rx_ctrl",
0016     "rx_fcs_err",
0017     "rx_len_err",
0018     "rx_byte_cnt",
0019     "rx_runt",
0020     "rx_frag",
0021     "rx_sz_64",
0022     "rx_sz_65_127",
0023     "rx_sz_128_255",
0024     "rx_sz_256_511",
0025     "rx_sz_512_1023",
0026     "rx_sz_1024_1518",
0027     "rx_sz_1519_max",
0028     "rx_sz_ov",
0029     "rx_rxf_ov",
0030     "rx_align_err",
0031     "rx_bcast_byte_cnt",
0032     "rx_mcast_byte_cnt",
0033     "rx_err_addr",
0034     "rx_crc_align",
0035     "rx_jabbers",
0036     "tx_ok",
0037     "tx_bcast",
0038     "tx_mcast",
0039     "tx_pause",
0040     "tx_exc_defer",
0041     "tx_ctrl",
0042     "tx_defer",
0043     "tx_byte_cnt",
0044     "tx_sz_64",
0045     "tx_sz_65_127",
0046     "tx_sz_128_255",
0047     "tx_sz_256_511",
0048     "tx_sz_512_1023",
0049     "tx_sz_1024_1518",
0050     "tx_sz_1519_max",
0051     "tx_1_col",
0052     "tx_2_col",
0053     "tx_late_col",
0054     "tx_abort_col",
0055     "tx_underrun",
0056     "tx_rd_eop",
0057     "tx_len_err",
0058     "tx_trunc",
0059     "tx_bcast_byte",
0060     "tx_mcast_byte",
0061     "tx_col",
0062 };
0063 
0064 #define EMAC_STATS_LEN  ARRAY_SIZE(emac_ethtool_stat_strings)
0065 
0066 static u32 emac_get_msglevel(struct net_device *netdev)
0067 {
0068     struct emac_adapter *adpt = netdev_priv(netdev);
0069 
0070     return adpt->msg_enable;
0071 }
0072 
0073 static void emac_set_msglevel(struct net_device *netdev, u32 data)
0074 {
0075     struct emac_adapter *adpt = netdev_priv(netdev);
0076 
0077     adpt->msg_enable = data;
0078 }
0079 
0080 static int emac_get_sset_count(struct net_device *netdev, int sset)
0081 {
0082     switch (sset) {
0083     case ETH_SS_PRIV_FLAGS:
0084         return 1;
0085     case ETH_SS_STATS:
0086         return EMAC_STATS_LEN;
0087     default:
0088         return -EOPNOTSUPP;
0089     }
0090 }
0091 
0092 static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
0093 {
0094     unsigned int i;
0095 
0096     switch (stringset) {
0097     case ETH_SS_PRIV_FLAGS:
0098         strcpy(data, "single-pause-mode");
0099         break;
0100 
0101     case ETH_SS_STATS:
0102         for (i = 0; i < EMAC_STATS_LEN; i++) {
0103             strscpy(data, emac_ethtool_stat_strings[i],
0104                 ETH_GSTRING_LEN);
0105             data += ETH_GSTRING_LEN;
0106         }
0107         break;
0108     }
0109 }
0110 
0111 static void emac_get_ethtool_stats(struct net_device *netdev,
0112                    struct ethtool_stats *stats,
0113                    u64 *data)
0114 {
0115     struct emac_adapter *adpt = netdev_priv(netdev);
0116 
0117     spin_lock(&adpt->stats.lock);
0118 
0119     emac_update_hw_stats(adpt);
0120     memcpy(data, &adpt->stats, EMAC_STATS_LEN * sizeof(u64));
0121 
0122     spin_unlock(&adpt->stats.lock);
0123 }
0124 
0125 static int emac_nway_reset(struct net_device *netdev)
0126 {
0127     struct phy_device *phydev = netdev->phydev;
0128 
0129     if (!phydev)
0130         return -ENODEV;
0131 
0132     return genphy_restart_aneg(phydev);
0133 }
0134 
0135 static void emac_get_ringparam(struct net_device *netdev,
0136                    struct ethtool_ringparam *ring,
0137                    struct kernel_ethtool_ringparam *kernel_ring,
0138                    struct netlink_ext_ack *extack)
0139 {
0140     struct emac_adapter *adpt = netdev_priv(netdev);
0141 
0142     ring->rx_max_pending = EMAC_MAX_RX_DESCS;
0143     ring->tx_max_pending = EMAC_MAX_TX_DESCS;
0144     ring->rx_pending = adpt->rx_desc_cnt;
0145     ring->tx_pending = adpt->tx_desc_cnt;
0146 }
0147 
0148 static int emac_set_ringparam(struct net_device *netdev,
0149                   struct ethtool_ringparam *ring,
0150                   struct kernel_ethtool_ringparam *kernel_ring,
0151                   struct netlink_ext_ack *extack)
0152 {
0153     struct emac_adapter *adpt = netdev_priv(netdev);
0154 
0155     /* We don't have separate queues/rings for small/large frames, so
0156      * reject any attempt to specify those values separately.
0157      */
0158     if (ring->rx_mini_pending || ring->rx_jumbo_pending)
0159         return -EINVAL;
0160 
0161     adpt->tx_desc_cnt =
0162         clamp_val(ring->tx_pending, EMAC_MIN_TX_DESCS, EMAC_MAX_TX_DESCS);
0163 
0164     adpt->rx_desc_cnt =
0165         clamp_val(ring->rx_pending, EMAC_MIN_RX_DESCS, EMAC_MAX_RX_DESCS);
0166 
0167     if (netif_running(netdev))
0168         return emac_reinit_locked(adpt);
0169 
0170     return 0;
0171 }
0172 
0173 static void emac_get_pauseparam(struct net_device *netdev,
0174                 struct ethtool_pauseparam *pause)
0175 {
0176     struct emac_adapter *adpt = netdev_priv(netdev);
0177 
0178     pause->autoneg = adpt->automatic ? AUTONEG_ENABLE : AUTONEG_DISABLE;
0179     pause->rx_pause = adpt->rx_flow_control ? 1 : 0;
0180     pause->tx_pause = adpt->tx_flow_control ? 1 : 0;
0181 }
0182 
0183 static int emac_set_pauseparam(struct net_device *netdev,
0184                    struct ethtool_pauseparam *pause)
0185 {
0186     struct emac_adapter *adpt = netdev_priv(netdev);
0187 
0188     adpt->automatic = pause->autoneg == AUTONEG_ENABLE;
0189     adpt->rx_flow_control = pause->rx_pause != 0;
0190     adpt->tx_flow_control = pause->tx_pause != 0;
0191 
0192     if (netif_running(netdev))
0193         return emac_reinit_locked(adpt);
0194 
0195     return 0;
0196 }
0197 
0198 /* Selected registers that might want to track during runtime. */
0199 static const u16 emac_regs[] = {
0200     EMAC_DMA_MAS_CTRL,
0201     EMAC_MAC_CTRL,
0202     EMAC_TXQ_CTRL_0,
0203     EMAC_RXQ_CTRL_0,
0204     EMAC_DMA_CTRL,
0205     EMAC_INT_MASK,
0206     EMAC_AXI_MAST_CTRL,
0207     EMAC_CORE_HW_VERSION,
0208     EMAC_MISC_CTRL,
0209 };
0210 
0211 /* Every time emac_regs[] above is changed, increase this version number. */
0212 #define EMAC_REGS_VERSION   0
0213 
0214 #define EMAC_MAX_REG_SIZE   ARRAY_SIZE(emac_regs)
0215 
0216 static void emac_get_regs(struct net_device *netdev,
0217               struct ethtool_regs *regs, void *buff)
0218 {
0219     struct emac_adapter *adpt = netdev_priv(netdev);
0220     u32 *val = buff;
0221     unsigned int i;
0222 
0223     regs->version = EMAC_REGS_VERSION;
0224     regs->len = EMAC_MAX_REG_SIZE * sizeof(u32);
0225 
0226     for (i = 0; i < EMAC_MAX_REG_SIZE; i++)
0227         val[i] = readl(adpt->base + emac_regs[i]);
0228 }
0229 
0230 static int emac_get_regs_len(struct net_device *netdev)
0231 {
0232     return EMAC_MAX_REG_SIZE * sizeof(u32);
0233 }
0234 
0235 #define EMAC_PRIV_ENABLE_SINGLE_PAUSE   BIT(0)
0236 
0237 static int emac_set_priv_flags(struct net_device *netdev, u32 flags)
0238 {
0239     struct emac_adapter *adpt = netdev_priv(netdev);
0240 
0241     adpt->single_pause_mode = !!(flags & EMAC_PRIV_ENABLE_SINGLE_PAUSE);
0242 
0243     if (netif_running(netdev))
0244         return emac_reinit_locked(adpt);
0245 
0246     return 0;
0247 }
0248 
0249 static u32 emac_get_priv_flags(struct net_device *netdev)
0250 {
0251     struct emac_adapter *adpt = netdev_priv(netdev);
0252 
0253     return adpt->single_pause_mode ? EMAC_PRIV_ENABLE_SINGLE_PAUSE : 0;
0254 }
0255 
0256 static const struct ethtool_ops emac_ethtool_ops = {
0257     .get_link_ksettings = phy_ethtool_get_link_ksettings,
0258     .set_link_ksettings = phy_ethtool_set_link_ksettings,
0259 
0260     .get_msglevel    = emac_get_msglevel,
0261     .set_msglevel    = emac_set_msglevel,
0262 
0263     .get_sset_count  = emac_get_sset_count,
0264     .get_strings = emac_get_strings,
0265     .get_ethtool_stats = emac_get_ethtool_stats,
0266 
0267     .get_ringparam = emac_get_ringparam,
0268     .set_ringparam = emac_set_ringparam,
0269 
0270     .get_pauseparam = emac_get_pauseparam,
0271     .set_pauseparam = emac_set_pauseparam,
0272 
0273     .nway_reset = emac_nway_reset,
0274 
0275     .get_link = ethtool_op_get_link,
0276 
0277     .get_regs_len    = emac_get_regs_len,
0278     .get_regs        = emac_get_regs,
0279 
0280     .set_priv_flags = emac_set_priv_flags,
0281     .get_priv_flags = emac_get_priv_flags,
0282 };
0283 
0284 void emac_set_ethtool_ops(struct net_device *netdev)
0285 {
0286     netdev->ethtool_ops = &emac_ethtool_ops;
0287 }