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