1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Applied Micro X-Gene SoC Ethernet v2 Driver 4 * 5 * Copyright (c) 2017, Applied Micro Circuits Corporation 6 * Author(s): Iyappan Subramanian <isubramanian@apm.com> 7 * Keyur Chudgar <kchudgar@apm.com> 8 */ 9 10 #include "main.h" 11 12 #define XGE_STAT(m) { #m, offsetof(struct xge_pdata, stats.m) } 13 #define XGE_EXTD_STAT(m, n) \ 14 { \ 15 #m, \ 16 n, \ 17 0 \ 18 } 19 20 static const struct xge_gstrings_stats gstrings_stats[] = { 21 XGE_STAT(rx_packets), 22 XGE_STAT(tx_packets), 23 XGE_STAT(rx_bytes), 24 XGE_STAT(tx_bytes), 25 XGE_STAT(rx_errors) 26 }; 27 28 static struct xge_gstrings_extd_stats gstrings_extd_stats[] = { 29 XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64), 30 XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127), 31 XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255), 32 XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511), 33 XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K), 34 XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX), 35 XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV), 36 XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS), 37 XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA), 38 XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA), 39 XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF), 40 XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF), 41 XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO), 42 XGE_EXTD_STAT(rx_align_err_cntr, RALN), 43 XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR), 44 XGE_EXTD_STAT(rx_code_err_cntr, RCDE), 45 XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE), 46 XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND), 47 XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR), 48 XGE_EXTD_STAT(rx_fragments_cntr, RFRG), 49 XGE_EXTD_STAT(rx_jabber_cntr, RJBR), 50 XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP), 51 XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA), 52 XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA), 53 XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF), 54 XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR), 55 XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF), 56 XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL), 57 XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL), 58 XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL), 59 XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL), 60 XGE_EXTD_STAT(tx_total_col_cntr, TNCL), 61 XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH), 62 XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP), 63 XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR), 64 XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS), 65 XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF), 66 XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR), 67 XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND), 68 XGE_EXTD_STAT(tx_fragments_cntr, TFRG) 69 }; 70 71 #define XGE_STATS_LEN ARRAY_SIZE(gstrings_stats) 72 #define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats) 73 74 static void xge_mac_get_extd_stats(struct xge_pdata *pdata) 75 { 76 u32 data; 77 int i; 78 79 for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 80 data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr); 81 gstrings_extd_stats[i].value += data; 82 } 83 } 84 85 static void xge_get_drvinfo(struct net_device *ndev, 86 struct ethtool_drvinfo *info) 87 { 88 struct xge_pdata *pdata = netdev_priv(ndev); 89 struct platform_device *pdev = pdata->pdev; 90 91 strcpy(info->driver, "xgene-enet-v2"); 92 strcpy(info->version, XGENE_ENET_V2_VERSION); 93 snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); 94 sprintf(info->bus_info, "%s", pdev->name); 95 } 96 97 static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 98 { 99 u8 *p = data; 100 int i; 101 102 if (stringset != ETH_SS_STATS) 103 return; 104 105 for (i = 0; i < XGE_STATS_LEN; i++) { 106 memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); 107 p += ETH_GSTRING_LEN; 108 } 109 110 for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 111 memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN); 112 p += ETH_GSTRING_LEN; 113 } 114 } 115 116 static int xge_get_sset_count(struct net_device *ndev, int sset) 117 { 118 if (sset != ETH_SS_STATS) 119 return -EINVAL; 120 121 return XGE_STATS_LEN + XGE_EXTD_STATS_LEN; 122 } 123 124 static void xge_get_ethtool_stats(struct net_device *ndev, 125 struct ethtool_stats *dummy, 126 u64 *data) 127 { 128 void *pdata = netdev_priv(ndev); 129 int i; 130 131 for (i = 0; i < XGE_STATS_LEN; i++) 132 *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); 133 134 xge_mac_get_extd_stats(pdata); 135 136 for (i = 0; i < XGE_EXTD_STATS_LEN; i++) 137 *data++ = gstrings_extd_stats[i].value; 138 } 139 140 static int xge_get_link_ksettings(struct net_device *ndev, 141 struct ethtool_link_ksettings *cmd) 142 { 143 struct phy_device *phydev = ndev->phydev; 144 145 if (!phydev) 146 return -ENODEV; 147 148 phy_ethtool_ksettings_get(phydev, cmd); 149 150 return 0; 151 } 152 153 static int xge_set_link_ksettings(struct net_device *ndev, 154 const struct ethtool_link_ksettings *cmd) 155 { 156 struct phy_device *phydev = ndev->phydev; 157 158 if (!phydev) 159 return -ENODEV; 160 161 return phy_ethtool_ksettings_set(phydev, cmd); 162 } 163 164 static const struct ethtool_ops xge_ethtool_ops = { 165 .get_drvinfo = xge_get_drvinfo, 166 .get_link = ethtool_op_get_link, 167 .get_strings = xge_get_strings, 168 .get_sset_count = xge_get_sset_count, 169 .get_ethtool_stats = xge_get_ethtool_stats, 170 .get_link_ksettings = xge_get_link_ksettings, 171 .set_link_ksettings = xge_set_link_ksettings, 172 }; 173 174 void xge_set_ethtool_ops(struct net_device *ndev) 175 { 176 ndev->ethtool_ops = &xge_ethtool_ops; 177 } 178