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