1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Applied Micro X-Gene SoC Ethernet v2 Driver
4 *
5 * Copyright (c) 2017, Applied Micro Circuits Corporation
6 * Author(s): Iyappan Subramanian <isubramanian@apm.com>
7 *	      Keyur Chudgar <kchudgar@apm.com>
8 */
9
10#include "main.h"
11
12#define XGE_STAT(m)		{ #m, offsetof(struct xge_pdata, stats.m) }
13#define XGE_EXTD_STAT(m, n)					\
14	{							\
15		#m,						\
16		n,						\
17		0						\
18	}
19
20static const struct xge_gstrings_stats gstrings_stats[] = {
21	XGE_STAT(rx_packets),
22	XGE_STAT(tx_packets),
23	XGE_STAT(rx_bytes),
24	XGE_STAT(tx_bytes),
25	XGE_STAT(rx_errors)
26};
27
28static struct xge_gstrings_extd_stats gstrings_extd_stats[] = {
29	XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64),
30	XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127),
31	XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255),
32	XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511),
33	XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K),
34	XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX),
35	XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV),
36	XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS),
37	XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA),
38	XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA),
39	XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF),
40	XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF),
41	XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO),
42	XGE_EXTD_STAT(rx_align_err_cntr, RALN),
43	XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR),
44	XGE_EXTD_STAT(rx_code_err_cntr, RCDE),
45	XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE),
46	XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND),
47	XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR),
48	XGE_EXTD_STAT(rx_fragments_cntr, RFRG),
49	XGE_EXTD_STAT(rx_jabber_cntr, RJBR),
50	XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP),
51	XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA),
52	XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA),
53	XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF),
54	XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR),
55	XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF),
56	XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL),
57	XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL),
58	XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL),
59	XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL),
60	XGE_EXTD_STAT(tx_total_col_cntr, TNCL),
61	XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH),
62	XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP),
63	XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR),
64	XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS),
65	XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF),
66	XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR),
67	XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND),
68	XGE_EXTD_STAT(tx_fragments_cntr, TFRG)
69};
70
71#define XGE_STATS_LEN		ARRAY_SIZE(gstrings_stats)
72#define XGE_EXTD_STATS_LEN	ARRAY_SIZE(gstrings_extd_stats)
73
74static void xge_mac_get_extd_stats(struct xge_pdata *pdata)
75{
76	u32 data;
77	int i;
78
79	for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
80		data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr);
81		gstrings_extd_stats[i].value += data;
82	}
83}
84
85static void xge_get_drvinfo(struct net_device *ndev,
86			    struct ethtool_drvinfo *info)
87{
88	struct xge_pdata *pdata = netdev_priv(ndev);
89	struct platform_device *pdev = pdata->pdev;
90
91	strcpy(info->driver, "xgene-enet-v2");
92	sprintf(info->bus_info, "%s", pdev->name);
93}
94
95static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
96{
97	u8 *p = data;
98	int i;
99
100	if (stringset != ETH_SS_STATS)
101		return;
102
103	for (i = 0; i < XGE_STATS_LEN; i++) {
104		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
105		p += ETH_GSTRING_LEN;
106	}
107
108	for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
109		memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
110		p += ETH_GSTRING_LEN;
111	}
112}
113
114static int xge_get_sset_count(struct net_device *ndev, int sset)
115{
116	if (sset != ETH_SS_STATS)
117		return -EINVAL;
118
119	return XGE_STATS_LEN + XGE_EXTD_STATS_LEN;
120}
121
122static void xge_get_ethtool_stats(struct net_device *ndev,
123				  struct ethtool_stats *dummy,
124				  u64 *data)
125{
126	void *pdata = netdev_priv(ndev);
127	int i;
128
129	for (i = 0; i < XGE_STATS_LEN; i++)
130		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
131
132	xge_mac_get_extd_stats(pdata);
133
134	for (i = 0; i < XGE_EXTD_STATS_LEN; i++)
135		*data++ = gstrings_extd_stats[i].value;
136}
137
138static int xge_get_link_ksettings(struct net_device *ndev,
139				  struct ethtool_link_ksettings *cmd)
140{
141	struct phy_device *phydev = ndev->phydev;
142
143	if (!phydev)
144		return -ENODEV;
145
146	phy_ethtool_ksettings_get(phydev, cmd);
147
148	return 0;
149}
150
151static int xge_set_link_ksettings(struct net_device *ndev,
152				  const struct ethtool_link_ksettings *cmd)
153{
154	struct phy_device *phydev = ndev->phydev;
155
156	if (!phydev)
157		return -ENODEV;
158
159	return phy_ethtool_ksettings_set(phydev, cmd);
160}
161
162static const struct ethtool_ops xge_ethtool_ops = {
163	.get_drvinfo = xge_get_drvinfo,
164	.get_link = ethtool_op_get_link,
165	.get_strings = xge_get_strings,
166	.get_sset_count = xge_get_sset_count,
167	.get_ethtool_stats = xge_get_ethtool_stats,
168	.get_link_ksettings = xge_get_link_ksettings,
169	.set_link_ksettings = xge_set_link_ksettings,
170};
171
172void xge_set_ethtool_ops(struct net_device *ndev)
173{
174	ndev->ethtool_ops = &xge_ethtool_ops;
175}
176