162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Applied Micro X-Gene SoC Ethernet v2 Driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2017, Applied Micro Circuits Corporation 662306a36Sopenharmony_ci * Author(s): Iyappan Subramanian <isubramanian@apm.com> 762306a36Sopenharmony_ci * Keyur Chudgar <kchudgar@apm.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "main.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define XGE_STAT(m) { #m, offsetof(struct xge_pdata, stats.m) } 1362306a36Sopenharmony_ci#define XGE_EXTD_STAT(m, n) \ 1462306a36Sopenharmony_ci { \ 1562306a36Sopenharmony_ci #m, \ 1662306a36Sopenharmony_ci n, \ 1762306a36Sopenharmony_ci 0 \ 1862306a36Sopenharmony_ci } 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic const struct xge_gstrings_stats gstrings_stats[] = { 2162306a36Sopenharmony_ci XGE_STAT(rx_packets), 2262306a36Sopenharmony_ci XGE_STAT(tx_packets), 2362306a36Sopenharmony_ci XGE_STAT(rx_bytes), 2462306a36Sopenharmony_ci XGE_STAT(tx_bytes), 2562306a36Sopenharmony_ci XGE_STAT(rx_errors) 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic struct xge_gstrings_extd_stats gstrings_extd_stats[] = { 2962306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64), 3062306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127), 3162306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255), 3262306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511), 3362306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K), 3462306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX), 3562306a36Sopenharmony_ci XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV), 3662306a36Sopenharmony_ci XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS), 3762306a36Sopenharmony_ci XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA), 3862306a36Sopenharmony_ci XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA), 3962306a36Sopenharmony_ci XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF), 4062306a36Sopenharmony_ci XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF), 4162306a36Sopenharmony_ci XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO), 4262306a36Sopenharmony_ci XGE_EXTD_STAT(rx_align_err_cntr, RALN), 4362306a36Sopenharmony_ci XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR), 4462306a36Sopenharmony_ci XGE_EXTD_STAT(rx_code_err_cntr, RCDE), 4562306a36Sopenharmony_ci XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE), 4662306a36Sopenharmony_ci XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND), 4762306a36Sopenharmony_ci XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR), 4862306a36Sopenharmony_ci XGE_EXTD_STAT(rx_fragments_cntr, RFRG), 4962306a36Sopenharmony_ci XGE_EXTD_STAT(rx_jabber_cntr, RJBR), 5062306a36Sopenharmony_ci XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP), 5162306a36Sopenharmony_ci XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA), 5262306a36Sopenharmony_ci XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA), 5362306a36Sopenharmony_ci XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF), 5462306a36Sopenharmony_ci XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR), 5562306a36Sopenharmony_ci XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF), 5662306a36Sopenharmony_ci XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL), 5762306a36Sopenharmony_ci XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL), 5862306a36Sopenharmony_ci XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL), 5962306a36Sopenharmony_ci XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL), 6062306a36Sopenharmony_ci XGE_EXTD_STAT(tx_total_col_cntr, TNCL), 6162306a36Sopenharmony_ci XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH), 6262306a36Sopenharmony_ci XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP), 6362306a36Sopenharmony_ci XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR), 6462306a36Sopenharmony_ci XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS), 6562306a36Sopenharmony_ci XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF), 6662306a36Sopenharmony_ci XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR), 6762306a36Sopenharmony_ci XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND), 6862306a36Sopenharmony_ci XGE_EXTD_STAT(tx_fragments_cntr, TFRG) 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define XGE_STATS_LEN ARRAY_SIZE(gstrings_stats) 7262306a36Sopenharmony_ci#define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void xge_mac_get_extd_stats(struct xge_pdata *pdata) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci u32 data; 7762306a36Sopenharmony_ci int i; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 8062306a36Sopenharmony_ci data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr); 8162306a36Sopenharmony_ci gstrings_extd_stats[i].value += data; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic void xge_get_drvinfo(struct net_device *ndev, 8662306a36Sopenharmony_ci struct ethtool_drvinfo *info) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct xge_pdata *pdata = netdev_priv(ndev); 8962306a36Sopenharmony_ci struct platform_device *pdev = pdata->pdev; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci strcpy(info->driver, "xgene-enet-v2"); 9262306a36Sopenharmony_ci sprintf(info->bus_info, "%s", pdev->name); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci u8 *p = data; 9862306a36Sopenharmony_ci int i; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if (stringset != ETH_SS_STATS) 10162306a36Sopenharmony_ci return; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci for (i = 0; i < XGE_STATS_LEN; i++) { 10462306a36Sopenharmony_ci memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); 10562306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 10962306a36Sopenharmony_ci memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN); 11062306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic int xge_get_sset_count(struct net_device *ndev, int sset) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci if (sset != ETH_SS_STATS) 11762306a36Sopenharmony_ci return -EINVAL; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return XGE_STATS_LEN + XGE_EXTD_STATS_LEN; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic void xge_get_ethtool_stats(struct net_device *ndev, 12362306a36Sopenharmony_ci struct ethtool_stats *dummy, 12462306a36Sopenharmony_ci u64 *data) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci void *pdata = netdev_priv(ndev); 12762306a36Sopenharmony_ci int i; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci for (i = 0; i < XGE_STATS_LEN; i++) 13062306a36Sopenharmony_ci *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci xge_mac_get_extd_stats(pdata); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci for (i = 0; i < XGE_EXTD_STATS_LEN; i++) 13562306a36Sopenharmony_ci *data++ = gstrings_extd_stats[i].value; 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic int xge_get_link_ksettings(struct net_device *ndev, 13962306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct phy_device *phydev = ndev->phydev; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (!phydev) 14462306a36Sopenharmony_ci return -ENODEV; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci phy_ethtool_ksettings_get(phydev, cmd); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci return 0; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic int xge_set_link_ksettings(struct net_device *ndev, 15262306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct phy_device *phydev = ndev->phydev; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (!phydev) 15762306a36Sopenharmony_ci return -ENODEV; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci return phy_ethtool_ksettings_set(phydev, cmd); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic const struct ethtool_ops xge_ethtool_ops = { 16362306a36Sopenharmony_ci .get_drvinfo = xge_get_drvinfo, 16462306a36Sopenharmony_ci .get_link = ethtool_op_get_link, 16562306a36Sopenharmony_ci .get_strings = xge_get_strings, 16662306a36Sopenharmony_ci .get_sset_count = xge_get_sset_count, 16762306a36Sopenharmony_ci .get_ethtool_stats = xge_get_ethtool_stats, 16862306a36Sopenharmony_ci .get_link_ksettings = xge_get_link_ksettings, 16962306a36Sopenharmony_ci .set_link_ksettings = xge_set_link_ksettings, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_civoid xge_set_ethtool_ops(struct net_device *ndev) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci ndev->ethtool_ops = &xge_ethtool_ops; 17562306a36Sopenharmony_ci} 176