xref: /openbmc/linux/drivers/net/fjes/fjes_ethtool.c (revision 786eec27cbb1713caf3b33538a877a21e779d3bc)
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