1617d795cSIyappan Subramanian /* 2617d795cSIyappan Subramanian * Applied Micro X-Gene SoC Ethernet v2 Driver 3617d795cSIyappan Subramanian * 4617d795cSIyappan Subramanian * Copyright (c) 2017, Applied Micro Circuits Corporation 5617d795cSIyappan Subramanian * Author(s): Iyappan Subramanian <isubramanian@apm.com> 6617d795cSIyappan Subramanian * Keyur Chudgar <kchudgar@apm.com> 7617d795cSIyappan Subramanian * 8617d795cSIyappan Subramanian * This program is free software; you can redistribute it and/or modify it 9617d795cSIyappan Subramanian * under the terms of the GNU General Public License as published by the 10617d795cSIyappan Subramanian * Free Software Foundation; either version 2 of the License, or (at your 11617d795cSIyappan Subramanian * option) any later version. 12617d795cSIyappan Subramanian * 13617d795cSIyappan Subramanian * This program is distributed in the hope that it will be useful, 14617d795cSIyappan Subramanian * but WITHOUT ANY WARRANTY; without even the implied warranty of 15617d795cSIyappan Subramanian * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16617d795cSIyappan Subramanian * GNU General Public License for more details. 17617d795cSIyappan Subramanian * 18617d795cSIyappan Subramanian * You should have received a copy of the GNU General Public License 19617d795cSIyappan Subramanian * along with this program. If not, see <http://www.gnu.org/licenses/>. 20617d795cSIyappan Subramanian */ 21617d795cSIyappan Subramanian 22617d795cSIyappan Subramanian #include "main.h" 23617d795cSIyappan Subramanian 24617d795cSIyappan Subramanian #define XGE_STAT(m) { #m, offsetof(struct xge_pdata, stats.m) } 25*e05ddafdSIyappan Subramanian #define XGE_EXTD_STAT(m, n) \ 26*e05ddafdSIyappan Subramanian { \ 27*e05ddafdSIyappan Subramanian #m, \ 28*e05ddafdSIyappan Subramanian n, \ 29*e05ddafdSIyappan Subramanian 0 \ 30*e05ddafdSIyappan Subramanian } 31617d795cSIyappan Subramanian 32617d795cSIyappan Subramanian static const struct xge_gstrings_stats gstrings_stats[] = { 33617d795cSIyappan Subramanian XGE_STAT(rx_packets), 34617d795cSIyappan Subramanian XGE_STAT(tx_packets), 35617d795cSIyappan Subramanian XGE_STAT(rx_bytes), 36617d795cSIyappan Subramanian XGE_STAT(tx_bytes), 37617d795cSIyappan Subramanian XGE_STAT(rx_errors) 38617d795cSIyappan Subramanian }; 39617d795cSIyappan Subramanian 40*e05ddafdSIyappan Subramanian static struct xge_gstrings_extd_stats gstrings_extd_stats[] = { 41*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64), 42*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127), 43*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255), 44*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511), 45*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K), 46*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX), 47*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV), 48*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS), 49*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA), 50*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA), 51*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF), 52*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF), 53*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO), 54*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_align_err_cntr, RALN), 55*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR), 56*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_code_err_cntr, RCDE), 57*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE), 58*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND), 59*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR), 60*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_fragments_cntr, RFRG), 61*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_jabber_cntr, RJBR), 62*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP), 63*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA), 64*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA), 65*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF), 66*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR), 67*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF), 68*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL), 69*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL), 70*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL), 71*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL), 72*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_total_col_cntr, TNCL), 73*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH), 74*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP), 75*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR), 76*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS), 77*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF), 78*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR), 79*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND), 80*e05ddafdSIyappan Subramanian XGE_EXTD_STAT(tx_fragments_cntr, TFRG) 81*e05ddafdSIyappan Subramanian }; 82*e05ddafdSIyappan Subramanian 83617d795cSIyappan Subramanian #define XGE_STATS_LEN ARRAY_SIZE(gstrings_stats) 84*e05ddafdSIyappan Subramanian #define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats) 85*e05ddafdSIyappan Subramanian 86*e05ddafdSIyappan Subramanian static void xge_mac_get_extd_stats(struct xge_pdata *pdata) 87*e05ddafdSIyappan Subramanian { 88*e05ddafdSIyappan Subramanian u32 data; 89*e05ddafdSIyappan Subramanian int i; 90*e05ddafdSIyappan Subramanian 91*e05ddafdSIyappan Subramanian for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 92*e05ddafdSIyappan Subramanian data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr); 93*e05ddafdSIyappan Subramanian gstrings_extd_stats[i].value += data; 94*e05ddafdSIyappan Subramanian } 95*e05ddafdSIyappan Subramanian } 96617d795cSIyappan Subramanian 97617d795cSIyappan Subramanian static void xge_get_drvinfo(struct net_device *ndev, 98617d795cSIyappan Subramanian struct ethtool_drvinfo *info) 99617d795cSIyappan Subramanian { 100617d795cSIyappan Subramanian struct xge_pdata *pdata = netdev_priv(ndev); 101617d795cSIyappan Subramanian struct platform_device *pdev = pdata->pdev; 102617d795cSIyappan Subramanian 103617d795cSIyappan Subramanian strcpy(info->driver, "xgene-enet-v2"); 104617d795cSIyappan Subramanian strcpy(info->version, XGENE_ENET_V2_VERSION); 105617d795cSIyappan Subramanian snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); 106617d795cSIyappan Subramanian sprintf(info->bus_info, "%s", pdev->name); 107617d795cSIyappan Subramanian } 108617d795cSIyappan Subramanian 109617d795cSIyappan Subramanian static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 110617d795cSIyappan Subramanian { 111617d795cSIyappan Subramanian u8 *p = data; 112617d795cSIyappan Subramanian int i; 113617d795cSIyappan Subramanian 114617d795cSIyappan Subramanian if (stringset != ETH_SS_STATS) 115617d795cSIyappan Subramanian return; 116617d795cSIyappan Subramanian 117617d795cSIyappan Subramanian for (i = 0; i < XGE_STATS_LEN; i++) { 118617d795cSIyappan Subramanian memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); 119617d795cSIyappan Subramanian p += ETH_GSTRING_LEN; 120617d795cSIyappan Subramanian } 121*e05ddafdSIyappan Subramanian 122*e05ddafdSIyappan Subramanian for (i = 0; i < XGE_EXTD_STATS_LEN; i++) { 123*e05ddafdSIyappan Subramanian memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN); 124*e05ddafdSIyappan Subramanian p += ETH_GSTRING_LEN; 125*e05ddafdSIyappan Subramanian } 126617d795cSIyappan Subramanian } 127617d795cSIyappan Subramanian 128617d795cSIyappan Subramanian static int xge_get_sset_count(struct net_device *ndev, int sset) 129617d795cSIyappan Subramanian { 130617d795cSIyappan Subramanian if (sset != ETH_SS_STATS) 131617d795cSIyappan Subramanian return -EINVAL; 132617d795cSIyappan Subramanian 133*e05ddafdSIyappan Subramanian return XGE_STATS_LEN + XGE_EXTD_STATS_LEN; 134617d795cSIyappan Subramanian } 135617d795cSIyappan Subramanian 136617d795cSIyappan Subramanian static void xge_get_ethtool_stats(struct net_device *ndev, 137617d795cSIyappan Subramanian struct ethtool_stats *dummy, 138617d795cSIyappan Subramanian u64 *data) 139617d795cSIyappan Subramanian { 140617d795cSIyappan Subramanian void *pdata = netdev_priv(ndev); 141617d795cSIyappan Subramanian int i; 142617d795cSIyappan Subramanian 143617d795cSIyappan Subramanian for (i = 0; i < XGE_STATS_LEN; i++) 144617d795cSIyappan Subramanian *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); 145*e05ddafdSIyappan Subramanian 146*e05ddafdSIyappan Subramanian xge_mac_get_extd_stats(pdata); 147*e05ddafdSIyappan Subramanian 148*e05ddafdSIyappan Subramanian for (i = 0; i < XGE_EXTD_STATS_LEN; i++) 149*e05ddafdSIyappan Subramanian *data++ = gstrings_extd_stats[i].value; 150617d795cSIyappan Subramanian } 151617d795cSIyappan Subramanian 152617d795cSIyappan Subramanian static int xge_get_link_ksettings(struct net_device *ndev, 153617d795cSIyappan Subramanian struct ethtool_link_ksettings *cmd) 154617d795cSIyappan Subramanian { 155617d795cSIyappan Subramanian struct phy_device *phydev = ndev->phydev; 156617d795cSIyappan Subramanian 157617d795cSIyappan Subramanian if (!phydev) 158617d795cSIyappan Subramanian return -ENODEV; 159617d795cSIyappan Subramanian 160617d795cSIyappan Subramanian return phy_ethtool_ksettings_get(phydev, cmd); 161617d795cSIyappan Subramanian } 162617d795cSIyappan Subramanian 163617d795cSIyappan Subramanian static int xge_set_link_ksettings(struct net_device *ndev, 164617d795cSIyappan Subramanian const struct ethtool_link_ksettings *cmd) 165617d795cSIyappan Subramanian { 166617d795cSIyappan Subramanian struct phy_device *phydev = ndev->phydev; 167617d795cSIyappan Subramanian 168617d795cSIyappan Subramanian if (!phydev) 169617d795cSIyappan Subramanian return -ENODEV; 170617d795cSIyappan Subramanian 171617d795cSIyappan Subramanian return phy_ethtool_ksettings_set(phydev, cmd); 172617d795cSIyappan Subramanian } 173617d795cSIyappan Subramanian 174617d795cSIyappan Subramanian static const struct ethtool_ops xge_ethtool_ops = { 175617d795cSIyappan Subramanian .get_drvinfo = xge_get_drvinfo, 176617d795cSIyappan Subramanian .get_link = ethtool_op_get_link, 177617d795cSIyappan Subramanian .get_strings = xge_get_strings, 178617d795cSIyappan Subramanian .get_sset_count = xge_get_sset_count, 179617d795cSIyappan Subramanian .get_ethtool_stats = xge_get_ethtool_stats, 180617d795cSIyappan Subramanian .get_link_ksettings = xge_get_link_ksettings, 181617d795cSIyappan Subramanian .set_link_ksettings = xge_set_link_ksettings, 182617d795cSIyappan Subramanian }; 183617d795cSIyappan Subramanian 184617d795cSIyappan Subramanian void xge_set_ethtool_ops(struct net_device *ndev) 185617d795cSIyappan Subramanian { 186617d795cSIyappan Subramanian ndev->ethtool_ops = &xge_ethtool_ops; 187617d795cSIyappan Subramanian } 188