1786eec27STaku Izumi /* 2786eec27STaku Izumi * FUJITSU Extended Socket Network Device driver 3786eec27STaku Izumi * Copyright (c) 2015 FUJITSU LIMITED 4786eec27STaku Izumi * 5786eec27STaku Izumi * This program is free software; you can redistribute it and/or modify it 6786eec27STaku Izumi * under the terms and conditions of the GNU General Public License, 7786eec27STaku Izumi * version 2, as published by the Free Software Foundation. 8786eec27STaku Izumi * 9786eec27STaku Izumi * This program is distributed in the hope it will be useful, but WITHOUT 10786eec27STaku Izumi * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11786eec27STaku Izumi * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12786eec27STaku Izumi * more details. 13786eec27STaku Izumi * 14786eec27STaku Izumi * You should have received a copy of the GNU General Public License along with 15786eec27STaku Izumi * this program; if not, see <http://www.gnu.org/licenses/>. 16786eec27STaku Izumi * 17786eec27STaku Izumi * The full GNU General Public License is included in this distribution in 18786eec27STaku Izumi * the file called "COPYING". 19786eec27STaku Izumi * 20786eec27STaku Izumi */ 21786eec27STaku Izumi 22786eec27STaku Izumi /* ethtool support for fjes */ 23786eec27STaku Izumi 24786eec27STaku Izumi #include <linux/vmalloc.h> 25786eec27STaku Izumi #include <linux/netdevice.h> 26786eec27STaku Izumi #include <linux/ethtool.h> 27786eec27STaku Izumi #include <linux/platform_device.h> 28786eec27STaku Izumi 29786eec27STaku Izumi #include "fjes.h" 30786eec27STaku Izumi 31786eec27STaku Izumi struct fjes_stats { 32786eec27STaku Izumi char stat_string[ETH_GSTRING_LEN]; 33786eec27STaku Izumi int sizeof_stat; 34786eec27STaku Izumi int stat_offset; 35786eec27STaku Izumi }; 36786eec27STaku Izumi 37786eec27STaku Izumi #define FJES_STAT(name, stat) { \ 38786eec27STaku Izumi .stat_string = name, \ 39786eec27STaku Izumi .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \ 40786eec27STaku Izumi .stat_offset = offsetof(struct fjes_adapter, stat) \ 41786eec27STaku Izumi } 42786eec27STaku Izumi 43786eec27STaku Izumi static const struct fjes_stats fjes_gstrings_stats[] = { 44786eec27STaku Izumi FJES_STAT("rx_packets", stats64.rx_packets), 45786eec27STaku Izumi FJES_STAT("tx_packets", stats64.tx_packets), 46786eec27STaku Izumi FJES_STAT("rx_bytes", stats64.rx_bytes), 47786eec27STaku Izumi FJES_STAT("tx_bytes", stats64.rx_bytes), 48786eec27STaku Izumi FJES_STAT("rx_dropped", stats64.rx_dropped), 49786eec27STaku Izumi FJES_STAT("tx_dropped", stats64.tx_dropped), 50786eec27STaku Izumi }; 51786eec27STaku Izumi 52786eec27STaku Izumi static void fjes_get_ethtool_stats(struct net_device *netdev, 53786eec27STaku Izumi struct ethtool_stats *stats, u64 *data) 54786eec27STaku Izumi { 55786eec27STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 56786eec27STaku Izumi char *p; 57786eec27STaku Izumi int i; 58786eec27STaku Izumi 59786eec27STaku Izumi for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) { 60786eec27STaku Izumi p = (char *)adapter + fjes_gstrings_stats[i].stat_offset; 61786eec27STaku Izumi data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64)) 62786eec27STaku Izumi ? *(u64 *)p : *(u32 *)p; 63786eec27STaku Izumi } 64786eec27STaku Izumi } 65786eec27STaku Izumi 66786eec27STaku Izumi static void fjes_get_strings(struct net_device *netdev, 67786eec27STaku Izumi u32 stringset, u8 *data) 68786eec27STaku Izumi { 69786eec27STaku Izumi u8 *p = data; 70786eec27STaku Izumi int i; 71786eec27STaku Izumi 72786eec27STaku Izumi switch (stringset) { 73786eec27STaku Izumi case ETH_SS_STATS: 74786eec27STaku Izumi for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) { 75786eec27STaku Izumi memcpy(p, fjes_gstrings_stats[i].stat_string, 76786eec27STaku Izumi ETH_GSTRING_LEN); 77786eec27STaku Izumi p += ETH_GSTRING_LEN; 78786eec27STaku Izumi } 79786eec27STaku Izumi break; 80786eec27STaku Izumi } 81786eec27STaku Izumi } 82786eec27STaku Izumi 83786eec27STaku Izumi static int fjes_get_sset_count(struct net_device *netdev, int sset) 84786eec27STaku Izumi { 85786eec27STaku Izumi switch (sset) { 86786eec27STaku Izumi case ETH_SS_STATS: 87786eec27STaku Izumi return ARRAY_SIZE(fjes_gstrings_stats); 88786eec27STaku Izumi default: 89786eec27STaku Izumi return -EOPNOTSUPP; 90786eec27STaku Izumi } 91786eec27STaku Izumi } 92786eec27STaku Izumi 93786eec27STaku Izumi static void fjes_get_drvinfo(struct net_device *netdev, 94786eec27STaku Izumi struct ethtool_drvinfo *drvinfo) 95786eec27STaku Izumi { 96786eec27STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 97786eec27STaku Izumi struct platform_device *plat_dev; 98786eec27STaku Izumi 99786eec27STaku Izumi plat_dev = adapter->plat_dev; 100786eec27STaku Izumi 101786eec27STaku Izumi strlcpy(drvinfo->driver, fjes_driver_name, sizeof(drvinfo->driver)); 102786eec27STaku Izumi strlcpy(drvinfo->version, fjes_driver_version, 103786eec27STaku Izumi sizeof(drvinfo->version)); 104786eec27STaku Izumi 105786eec27STaku Izumi strlcpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version)); 106786eec27STaku Izumi snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), 107786eec27STaku Izumi "platform:%s", plat_dev->name); 108786eec27STaku Izumi } 109786eec27STaku Izumi 110786eec27STaku Izumi static int fjes_get_settings(struct net_device *netdev, 111786eec27STaku Izumi struct ethtool_cmd *ecmd) 112786eec27STaku Izumi { 113786eec27STaku Izumi ecmd->supported = 0; 114786eec27STaku Izumi ecmd->advertising = 0; 115786eec27STaku Izumi ecmd->duplex = DUPLEX_FULL; 116786eec27STaku Izumi ecmd->autoneg = AUTONEG_DISABLE; 117786eec27STaku Izumi ecmd->transceiver = XCVR_DUMMY1; 118786eec27STaku Izumi ecmd->port = PORT_NONE; 119786eec27STaku Izumi ethtool_cmd_speed_set(ecmd, 20000); /* 20Gb/s */ 120786eec27STaku Izumi 121786eec27STaku Izumi return 0; 122786eec27STaku Izumi } 123786eec27STaku Izumi 124*462d8074STaku Izumi static int fjes_get_regs_len(struct net_device *netdev) 125*462d8074STaku Izumi { 126*462d8074STaku Izumi #define FJES_REGS_LEN 37 127*462d8074STaku Izumi return FJES_REGS_LEN * sizeof(u32); 128*462d8074STaku Izumi } 129*462d8074STaku Izumi 130*462d8074STaku Izumi static void fjes_get_regs(struct net_device *netdev, 131*462d8074STaku Izumi struct ethtool_regs *regs, void *p) 132*462d8074STaku Izumi { 133*462d8074STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 134*462d8074STaku Izumi struct fjes_hw *hw = &adapter->hw; 135*462d8074STaku Izumi u32 *regs_buff = p; 136*462d8074STaku Izumi 137*462d8074STaku Izumi memset(p, 0, FJES_REGS_LEN * sizeof(u32)); 138*462d8074STaku Izumi 139*462d8074STaku Izumi regs->version = 1; 140*462d8074STaku Izumi 141*462d8074STaku Izumi /* Information registers */ 142*462d8074STaku Izumi regs_buff[0] = rd32(XSCT_OWNER_EPID); 143*462d8074STaku Izumi regs_buff[1] = rd32(XSCT_MAX_EP); 144*462d8074STaku Izumi 145*462d8074STaku Izumi /* Device Control registers */ 146*462d8074STaku Izumi regs_buff[4] = rd32(XSCT_DCTL); 147*462d8074STaku Izumi 148*462d8074STaku Izumi /* Command Control registers */ 149*462d8074STaku Izumi regs_buff[8] = rd32(XSCT_CR); 150*462d8074STaku Izumi regs_buff[9] = rd32(XSCT_CS); 151*462d8074STaku Izumi regs_buff[10] = rd32(XSCT_SHSTSAL); 152*462d8074STaku Izumi regs_buff[11] = rd32(XSCT_SHSTSAH); 153*462d8074STaku Izumi 154*462d8074STaku Izumi regs_buff[13] = rd32(XSCT_REQBL); 155*462d8074STaku Izumi regs_buff[14] = rd32(XSCT_REQBAL); 156*462d8074STaku Izumi regs_buff[15] = rd32(XSCT_REQBAH); 157*462d8074STaku Izumi 158*462d8074STaku Izumi regs_buff[17] = rd32(XSCT_RESPBL); 159*462d8074STaku Izumi regs_buff[18] = rd32(XSCT_RESPBAL); 160*462d8074STaku Izumi regs_buff[19] = rd32(XSCT_RESPBAH); 161*462d8074STaku Izumi 162*462d8074STaku Izumi /* Interrupt Control registers */ 163*462d8074STaku Izumi regs_buff[32] = rd32(XSCT_IS); 164*462d8074STaku Izumi regs_buff[33] = rd32(XSCT_IMS); 165*462d8074STaku Izumi regs_buff[34] = rd32(XSCT_IMC); 166*462d8074STaku Izumi regs_buff[35] = rd32(XSCT_IG); 167*462d8074STaku Izumi regs_buff[36] = rd32(XSCT_ICTL); 168*462d8074STaku Izumi } 169*462d8074STaku Izumi 170786eec27STaku Izumi static const struct ethtool_ops fjes_ethtool_ops = { 171786eec27STaku Izumi .get_settings = fjes_get_settings, 172786eec27STaku Izumi .get_drvinfo = fjes_get_drvinfo, 173786eec27STaku Izumi .get_ethtool_stats = fjes_get_ethtool_stats, 174786eec27STaku Izumi .get_strings = fjes_get_strings, 175786eec27STaku Izumi .get_sset_count = fjes_get_sset_count, 176*462d8074STaku Izumi .get_regs = fjes_get_regs, 177*462d8074STaku Izumi .get_regs_len = fjes_get_regs_len, 178786eec27STaku Izumi }; 179786eec27STaku Izumi 180786eec27STaku Izumi void fjes_set_ethtool_ops(struct net_device *netdev) 181786eec27STaku Izumi { 182786eec27STaku Izumi netdev->ethtool_ops = &fjes_ethtool_ops; 183786eec27STaku Izumi } 184