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 struct xge_gstrings_stats { 25 char name[ETH_GSTRING_LEN]; 26 int offset; 27 }; 28 29 #define XGE_STAT(m) { #m, offsetof(struct xge_pdata, stats.m) } 30 31 static const struct xge_gstrings_stats gstrings_stats[] = { 32 XGE_STAT(rx_packets), 33 XGE_STAT(tx_packets), 34 XGE_STAT(rx_bytes), 35 XGE_STAT(tx_bytes), 36 XGE_STAT(rx_errors) 37 }; 38 39 #define XGE_STATS_LEN ARRAY_SIZE(gstrings_stats) 40 41 static void xge_get_drvinfo(struct net_device *ndev, 42 struct ethtool_drvinfo *info) 43 { 44 struct xge_pdata *pdata = netdev_priv(ndev); 45 struct platform_device *pdev = pdata->pdev; 46 47 strcpy(info->driver, "xgene-enet-v2"); 48 strcpy(info->version, XGENE_ENET_V2_VERSION); 49 snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); 50 sprintf(info->bus_info, "%s", pdev->name); 51 } 52 53 static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 54 { 55 u8 *p = data; 56 int i; 57 58 if (stringset != ETH_SS_STATS) 59 return; 60 61 for (i = 0; i < XGE_STATS_LEN; i++) { 62 memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); 63 p += ETH_GSTRING_LEN; 64 } 65 } 66 67 static int xge_get_sset_count(struct net_device *ndev, int sset) 68 { 69 if (sset != ETH_SS_STATS) 70 return -EINVAL; 71 72 return XGE_STATS_LEN; 73 } 74 75 static void xge_get_ethtool_stats(struct net_device *ndev, 76 struct ethtool_stats *dummy, 77 u64 *data) 78 { 79 void *pdata = netdev_priv(ndev); 80 int i; 81 82 for (i = 0; i < XGE_STATS_LEN; i++) 83 *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); 84 } 85 86 static int xge_get_link_ksettings(struct net_device *ndev, 87 struct ethtool_link_ksettings *cmd) 88 { 89 struct phy_device *phydev = ndev->phydev; 90 91 if (!phydev) 92 return -ENODEV; 93 94 return phy_ethtool_ksettings_get(phydev, cmd); 95 } 96 97 static int xge_set_link_ksettings(struct net_device *ndev, 98 const struct ethtool_link_ksettings *cmd) 99 { 100 struct phy_device *phydev = ndev->phydev; 101 102 if (!phydev) 103 return -ENODEV; 104 105 return phy_ethtool_ksettings_set(phydev, cmd); 106 } 107 108 static const struct ethtool_ops xge_ethtool_ops = { 109 .get_drvinfo = xge_get_drvinfo, 110 .get_link = ethtool_op_get_link, 111 .get_strings = xge_get_strings, 112 .get_sset_count = xge_get_sset_count, 113 .get_ethtool_stats = xge_get_ethtool_stats, 114 .get_link_ksettings = xge_get_link_ksettings, 115 .set_link_ksettings = xge_set_link_ksettings, 116 }; 117 118 void xge_set_ethtool_ops(struct net_device *ndev) 119 { 120 ndev->ethtool_ops = &xge_ethtool_ops; 121 } 122