1*786eec27STaku Izumi /* 2*786eec27STaku Izumi * FUJITSU Extended Socket Network Device driver 3*786eec27STaku Izumi * Copyright (c) 2015 FUJITSU LIMITED 4*786eec27STaku Izumi * 5*786eec27STaku Izumi * This program is free software; you can redistribute it and/or modify it 6*786eec27STaku Izumi * under the terms and conditions of the GNU General Public License, 7*786eec27STaku Izumi * version 2, as published by the Free Software Foundation. 8*786eec27STaku Izumi * 9*786eec27STaku Izumi * This program is distributed in the hope it will be useful, but WITHOUT 10*786eec27STaku Izumi * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*786eec27STaku Izumi * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*786eec27STaku Izumi * more details. 13*786eec27STaku Izumi * 14*786eec27STaku Izumi * You should have received a copy of the GNU General Public License along with 15*786eec27STaku Izumi * this program; if not, see <http://www.gnu.org/licenses/>. 16*786eec27STaku Izumi * 17*786eec27STaku Izumi * The full GNU General Public License is included in this distribution in 18*786eec27STaku Izumi * the file called "COPYING". 19*786eec27STaku Izumi * 20*786eec27STaku Izumi */ 21*786eec27STaku Izumi 22*786eec27STaku Izumi /* ethtool support for fjes */ 23*786eec27STaku Izumi 24*786eec27STaku Izumi #include <linux/vmalloc.h> 25*786eec27STaku Izumi #include <linux/netdevice.h> 26*786eec27STaku Izumi #include <linux/ethtool.h> 27*786eec27STaku Izumi #include <linux/platform_device.h> 28*786eec27STaku Izumi 29*786eec27STaku Izumi #include "fjes.h" 30*786eec27STaku Izumi 31*786eec27STaku Izumi struct fjes_stats { 32*786eec27STaku Izumi char stat_string[ETH_GSTRING_LEN]; 33*786eec27STaku Izumi int sizeof_stat; 34*786eec27STaku Izumi int stat_offset; 35*786eec27STaku Izumi }; 36*786eec27STaku Izumi 37*786eec27STaku Izumi #define FJES_STAT(name, stat) { \ 38*786eec27STaku Izumi .stat_string = name, \ 39*786eec27STaku Izumi .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \ 40*786eec27STaku Izumi .stat_offset = offsetof(struct fjes_adapter, stat) \ 41*786eec27STaku Izumi } 42*786eec27STaku Izumi 43*786eec27STaku Izumi static const struct fjes_stats fjes_gstrings_stats[] = { 44*786eec27STaku Izumi FJES_STAT("rx_packets", stats64.rx_packets), 45*786eec27STaku Izumi FJES_STAT("tx_packets", stats64.tx_packets), 46*786eec27STaku Izumi FJES_STAT("rx_bytes", stats64.rx_bytes), 47*786eec27STaku Izumi FJES_STAT("tx_bytes", stats64.rx_bytes), 48*786eec27STaku Izumi FJES_STAT("rx_dropped", stats64.rx_dropped), 49*786eec27STaku Izumi FJES_STAT("tx_dropped", stats64.tx_dropped), 50*786eec27STaku Izumi }; 51*786eec27STaku Izumi 52*786eec27STaku Izumi static void fjes_get_ethtool_stats(struct net_device *netdev, 53*786eec27STaku Izumi struct ethtool_stats *stats, u64 *data) 54*786eec27STaku Izumi { 55*786eec27STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 56*786eec27STaku Izumi char *p; 57*786eec27STaku Izumi int i; 58*786eec27STaku Izumi 59*786eec27STaku Izumi for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) { 60*786eec27STaku Izumi p = (char *)adapter + fjes_gstrings_stats[i].stat_offset; 61*786eec27STaku Izumi data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64)) 62*786eec27STaku Izumi ? *(u64 *)p : *(u32 *)p; 63*786eec27STaku Izumi } 64*786eec27STaku Izumi } 65*786eec27STaku Izumi 66*786eec27STaku Izumi static void fjes_get_strings(struct net_device *netdev, 67*786eec27STaku Izumi u32 stringset, u8 *data) 68*786eec27STaku Izumi { 69*786eec27STaku Izumi u8 *p = data; 70*786eec27STaku Izumi int i; 71*786eec27STaku Izumi 72*786eec27STaku Izumi switch (stringset) { 73*786eec27STaku Izumi case ETH_SS_STATS: 74*786eec27STaku Izumi for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) { 75*786eec27STaku Izumi memcpy(p, fjes_gstrings_stats[i].stat_string, 76*786eec27STaku Izumi ETH_GSTRING_LEN); 77*786eec27STaku Izumi p += ETH_GSTRING_LEN; 78*786eec27STaku Izumi } 79*786eec27STaku Izumi break; 80*786eec27STaku Izumi } 81*786eec27STaku Izumi } 82*786eec27STaku Izumi 83*786eec27STaku Izumi static int fjes_get_sset_count(struct net_device *netdev, int sset) 84*786eec27STaku Izumi { 85*786eec27STaku Izumi switch (sset) { 86*786eec27STaku Izumi case ETH_SS_STATS: 87*786eec27STaku Izumi return ARRAY_SIZE(fjes_gstrings_stats); 88*786eec27STaku Izumi default: 89*786eec27STaku Izumi return -EOPNOTSUPP; 90*786eec27STaku Izumi } 91*786eec27STaku Izumi } 92*786eec27STaku Izumi 93*786eec27STaku Izumi static void fjes_get_drvinfo(struct net_device *netdev, 94*786eec27STaku Izumi struct ethtool_drvinfo *drvinfo) 95*786eec27STaku Izumi { 96*786eec27STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 97*786eec27STaku Izumi struct platform_device *plat_dev; 98*786eec27STaku Izumi 99*786eec27STaku Izumi plat_dev = adapter->plat_dev; 100*786eec27STaku Izumi 101*786eec27STaku Izumi strlcpy(drvinfo->driver, fjes_driver_name, sizeof(drvinfo->driver)); 102*786eec27STaku Izumi strlcpy(drvinfo->version, fjes_driver_version, 103*786eec27STaku Izumi sizeof(drvinfo->version)); 104*786eec27STaku Izumi 105*786eec27STaku Izumi strlcpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version)); 106*786eec27STaku Izumi snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), 107*786eec27STaku Izumi "platform:%s", plat_dev->name); 108*786eec27STaku Izumi drvinfo->regdump_len = 0; 109*786eec27STaku Izumi drvinfo->eedump_len = 0; 110*786eec27STaku Izumi } 111*786eec27STaku Izumi 112*786eec27STaku Izumi static int fjes_get_settings(struct net_device *netdev, 113*786eec27STaku Izumi struct ethtool_cmd *ecmd) 114*786eec27STaku Izumi { 115*786eec27STaku Izumi ecmd->supported = 0; 116*786eec27STaku Izumi ecmd->advertising = 0; 117*786eec27STaku Izumi ecmd->duplex = DUPLEX_FULL; 118*786eec27STaku Izumi ecmd->autoneg = AUTONEG_DISABLE; 119*786eec27STaku Izumi ecmd->transceiver = XCVR_DUMMY1; 120*786eec27STaku Izumi ecmd->port = PORT_NONE; 121*786eec27STaku Izumi ethtool_cmd_speed_set(ecmd, 20000); /* 20Gb/s */ 122*786eec27STaku Izumi 123*786eec27STaku Izumi return 0; 124*786eec27STaku Izumi } 125*786eec27STaku Izumi 126*786eec27STaku Izumi static const struct ethtool_ops fjes_ethtool_ops = { 127*786eec27STaku Izumi .get_settings = fjes_get_settings, 128*786eec27STaku Izumi .get_drvinfo = fjes_get_drvinfo, 129*786eec27STaku Izumi .get_ethtool_stats = fjes_get_ethtool_stats, 130*786eec27STaku Izumi .get_strings = fjes_get_strings, 131*786eec27STaku Izumi .get_sset_count = fjes_get_sset_count, 132*786eec27STaku Izumi }; 133*786eec27STaku Izumi 134*786eec27STaku Izumi void fjes_set_ethtool_ops(struct net_device *netdev) 135*786eec27STaku Izumi { 136*786eec27STaku Izumi netdev->ethtool_ops = &fjes_ethtool_ops; 137*786eec27STaku Izumi } 138