1e6ad7673SIyappan Subramanian /* Applied Micro X-Gene SoC Ethernet Driver
2e6ad7673SIyappan Subramanian  *
3e6ad7673SIyappan Subramanian  * Copyright (c) 2014, Applied Micro Circuits Corporation
4e6ad7673SIyappan Subramanian  * Authors: Iyappan Subramanian <isubramanian@apm.com>
5e6ad7673SIyappan Subramanian  *
6e6ad7673SIyappan Subramanian  * This program is free software; you can redistribute  it and/or modify it
7e6ad7673SIyappan Subramanian  * under  the terms of  the GNU General  Public License as published by the
8e6ad7673SIyappan Subramanian  * Free Software Foundation;  either version 2 of the  License, or (at your
9e6ad7673SIyappan Subramanian  * option) any later version.
10e6ad7673SIyappan Subramanian  *
11e6ad7673SIyappan Subramanian  * This program is distributed in the hope that it will be useful,
12e6ad7673SIyappan Subramanian  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13e6ad7673SIyappan Subramanian  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14e6ad7673SIyappan Subramanian  * GNU General Public License for more details.
15e6ad7673SIyappan Subramanian  *
16e6ad7673SIyappan Subramanian  * You should have received a copy of the GNU General Public License
17e6ad7673SIyappan Subramanian  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18e6ad7673SIyappan Subramanian  */
19e6ad7673SIyappan Subramanian 
20e6ad7673SIyappan Subramanian #include <linux/ethtool.h>
21e6ad7673SIyappan Subramanian #include "xgene_enet_main.h"
22e6ad7673SIyappan Subramanian 
23e6ad7673SIyappan Subramanian struct xgene_gstrings_stats {
24e6ad7673SIyappan Subramanian 	char name[ETH_GSTRING_LEN];
25e6ad7673SIyappan Subramanian 	int offset;
26e6ad7673SIyappan Subramanian };
27e6ad7673SIyappan Subramanian 
28e6ad7673SIyappan Subramanian #define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
29e6ad7673SIyappan Subramanian 
30e6ad7673SIyappan Subramanian static const struct xgene_gstrings_stats gstrings_stats[] = {
31e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_packets),
32e6ad7673SIyappan Subramanian 	XGENE_STAT(tx_packets),
33e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_bytes),
34e6ad7673SIyappan Subramanian 	XGENE_STAT(tx_bytes),
35e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_errors),
36e6ad7673SIyappan Subramanian 	XGENE_STAT(tx_errors),
37e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_length_errors),
38e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_crc_errors),
39e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_frame_errors),
40e6ad7673SIyappan Subramanian 	XGENE_STAT(rx_fifo_errors)
41e6ad7673SIyappan Subramanian };
42e6ad7673SIyappan Subramanian 
43e6ad7673SIyappan Subramanian #define XGENE_STATS_LEN		ARRAY_SIZE(gstrings_stats)
44e6ad7673SIyappan Subramanian 
45e6ad7673SIyappan Subramanian static void xgene_get_drvinfo(struct net_device *ndev,
46e6ad7673SIyappan Subramanian 			      struct ethtool_drvinfo *info)
47e6ad7673SIyappan Subramanian {
48e6ad7673SIyappan Subramanian 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
49e6ad7673SIyappan Subramanian 	struct platform_device *pdev = pdata->pdev;
50e6ad7673SIyappan Subramanian 
51e6ad7673SIyappan Subramanian 	strcpy(info->driver, "xgene_enet");
52e6ad7673SIyappan Subramanian 	strcpy(info->version, XGENE_DRV_VERSION);
53e6ad7673SIyappan Subramanian 	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
54e6ad7673SIyappan Subramanian 	sprintf(info->bus_info, "%s", pdev->name);
55e6ad7673SIyappan Subramanian }
56e6ad7673SIyappan Subramanian 
57e6ad7673SIyappan Subramanian static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
58e6ad7673SIyappan Subramanian {
59e6ad7673SIyappan Subramanian 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
60e6ad7673SIyappan Subramanian 	struct phy_device *phydev = pdata->phy_dev;
61e6ad7673SIyappan Subramanian 
62e6ad7673SIyappan Subramanian 	if (phydev == NULL)
63e6ad7673SIyappan Subramanian 		return -ENODEV;
64e6ad7673SIyappan Subramanian 
65e6ad7673SIyappan Subramanian 	return phy_ethtool_gset(phydev, cmd);
66e6ad7673SIyappan Subramanian }
67e6ad7673SIyappan Subramanian 
68e6ad7673SIyappan Subramanian static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
69e6ad7673SIyappan Subramanian {
70e6ad7673SIyappan Subramanian 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
71e6ad7673SIyappan Subramanian 	struct phy_device *phydev = pdata->phy_dev;
72e6ad7673SIyappan Subramanian 
73e6ad7673SIyappan Subramanian 	if (phydev == NULL)
74e6ad7673SIyappan Subramanian 		return -ENODEV;
75e6ad7673SIyappan Subramanian 
76e6ad7673SIyappan Subramanian 	return phy_ethtool_sset(phydev, cmd);
77e6ad7673SIyappan Subramanian }
78e6ad7673SIyappan Subramanian 
79e6ad7673SIyappan Subramanian static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
80e6ad7673SIyappan Subramanian {
81e6ad7673SIyappan Subramanian 	int i;
82e6ad7673SIyappan Subramanian 	u8 *p = data;
83e6ad7673SIyappan Subramanian 
84e6ad7673SIyappan Subramanian 	if (stringset != ETH_SS_STATS)
85e6ad7673SIyappan Subramanian 		return;
86e6ad7673SIyappan Subramanian 
87e6ad7673SIyappan Subramanian 	for (i = 0; i < XGENE_STATS_LEN; i++) {
88e6ad7673SIyappan Subramanian 		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
89e6ad7673SIyappan Subramanian 		p += ETH_GSTRING_LEN;
90e6ad7673SIyappan Subramanian 	}
91e6ad7673SIyappan Subramanian }
92e6ad7673SIyappan Subramanian 
93e6ad7673SIyappan Subramanian static int xgene_get_sset_count(struct net_device *ndev, int sset)
94e6ad7673SIyappan Subramanian {
95e6ad7673SIyappan Subramanian 	if (sset != ETH_SS_STATS)
96e6ad7673SIyappan Subramanian 		return -EINVAL;
97e6ad7673SIyappan Subramanian 
98e6ad7673SIyappan Subramanian 	return XGENE_STATS_LEN;
99e6ad7673SIyappan Subramanian }
100e6ad7673SIyappan Subramanian 
101e6ad7673SIyappan Subramanian static void xgene_get_ethtool_stats(struct net_device *ndev,
102e6ad7673SIyappan Subramanian 				    struct ethtool_stats *dummy,
103e6ad7673SIyappan Subramanian 				    u64 *data)
104e6ad7673SIyappan Subramanian {
105e6ad7673SIyappan Subramanian 	void *pdata = netdev_priv(ndev);
106e6ad7673SIyappan Subramanian 	int i;
107e6ad7673SIyappan Subramanian 
108e6ad7673SIyappan Subramanian 	for (i = 0; i < XGENE_STATS_LEN; i++)
109e6ad7673SIyappan Subramanian 		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
110e6ad7673SIyappan Subramanian }
111e6ad7673SIyappan Subramanian 
112e6ad7673SIyappan Subramanian static const struct ethtool_ops xgene_ethtool_ops = {
113e6ad7673SIyappan Subramanian 	.get_drvinfo = xgene_get_drvinfo,
114e6ad7673SIyappan Subramanian 	.get_settings = xgene_get_settings,
115e6ad7673SIyappan Subramanian 	.set_settings = xgene_set_settings,
116e6ad7673SIyappan Subramanian 	.get_link = ethtool_op_get_link,
117e6ad7673SIyappan Subramanian 	.get_strings = xgene_get_strings,
118e6ad7673SIyappan Subramanian 	.get_sset_count = xgene_get_sset_count,
119e6ad7673SIyappan Subramanian 	.get_ethtool_stats = xgene_get_ethtool_stats
120e6ad7673SIyappan Subramanian };
121e6ad7673SIyappan Subramanian 
122e6ad7673SIyappan Subramanian void xgene_enet_set_ethtool_ops(struct net_device *ndev)
123e6ad7673SIyappan Subramanian {
124e6ad7673SIyappan Subramanian 	ndev->ethtool_ops = &xgene_ethtool_ops;
125e6ad7673SIyappan Subramanian }
126