stmmac_ethtool.c 25.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*******************************************************************************
  STMMAC Ethtool support

  Copyright (C) 2007-2009  STMicroelectronics Ltd

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/

#include <linux/etherdevice.h>
#include <linux/ethtool.h>
27
#include <linux/interrupt.h>
28
29
#include <linux/mii.h>
#include <linux/phy.h>
30
#include <linux/net_tstamp.h>
31
#include <asm/io.h>
32
33

#include "stmmac.h"
34
#include "dwmac_dma.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#define REG_SPACE_SIZE	0x1054
#define MAC100_ETHTOOL_NAME	"st_mac100"
#define GMAC_ETHTOOL_NAME	"st_gmac"

struct stmmac_stats {
	char stat_string[ETH_GSTRING_LEN];
	int sizeof_stat;
	int stat_offset;
};

#define STMMAC_STAT(m)	\
	{ #m, FIELD_SIZEOF(struct stmmac_extra_stats, m),	\
	offsetof(struct stmmac_priv, xstats.m)}

50
static const struct stmmac_stats stmmac_gstrings_stats[] = {
51
	/* Transmit errors */
52
53
54
	STMMAC_STAT(tx_underflow),
	STMMAC_STAT(tx_carrier),
	STMMAC_STAT(tx_losscarrier),
55
	STMMAC_STAT(vlan_tag),
56
57
58
59
60
61
	STMMAC_STAT(tx_deferred),
	STMMAC_STAT(tx_vlan),
	STMMAC_STAT(tx_jabber),
	STMMAC_STAT(tx_frame_flushed),
	STMMAC_STAT(tx_payload_error),
	STMMAC_STAT(tx_ip_header_error),
62
	/* Receive errors */
63
	STMMAC_STAT(rx_desc),
64
65
66
	STMMAC_STAT(sa_filter_fail),
	STMMAC_STAT(overflow_error),
	STMMAC_STAT(ipc_csum_error),
67
68
	STMMAC_STAT(rx_collision),
	STMMAC_STAT(rx_crc),
69
	STMMAC_STAT(dribbling_bit),
70
	STMMAC_STAT(rx_length),
71
72
73
74
75
76
77
78
	STMMAC_STAT(rx_mii),
	STMMAC_STAT(rx_multicast),
	STMMAC_STAT(rx_gmac_overflow),
	STMMAC_STAT(rx_watchdog),
	STMMAC_STAT(da_rx_filter_fail),
	STMMAC_STAT(sa_rx_filter_fail),
	STMMAC_STAT(rx_missed_cntr),
	STMMAC_STAT(rx_overflow_cntr),
79
	STMMAC_STAT(rx_vlan),
80
	/* Tx/Rx IRQ error info */
81
82
83
84
85
86
87
88
89
	STMMAC_STAT(tx_undeflow_irq),
	STMMAC_STAT(tx_process_stopped_irq),
	STMMAC_STAT(tx_jabber_irq),
	STMMAC_STAT(rx_overflow_irq),
	STMMAC_STAT(rx_buf_unav_irq),
	STMMAC_STAT(rx_process_stopped_irq),
	STMMAC_STAT(rx_watchdog_irq),
	STMMAC_STAT(tx_early_irq),
	STMMAC_STAT(fatal_bus_error_irq),
90
91
	/* Tx/Rx IRQ Events */
	STMMAC_STAT(rx_early_irq),
92
93
94
	STMMAC_STAT(threshold),
	STMMAC_STAT(tx_pkt_n),
	STMMAC_STAT(rx_pkt_n),
95
	STMMAC_STAT(normal_irq_n),
96
97
98
99
	STMMAC_STAT(rx_normal_irq_n),
	STMMAC_STAT(napi_poll),
	STMMAC_STAT(tx_normal_irq_n),
	STMMAC_STAT(tx_clean),
100
	STMMAC_STAT(tx_set_ic_bit),
101
102
	STMMAC_STAT(irq_receive_pmt_irq_n),
	/* MMC info */
103
104
105
	STMMAC_STAT(mmc_tx_irq_n),
	STMMAC_STAT(mmc_rx_irq_n),
	STMMAC_STAT(mmc_rx_csum_offload_irq_n),
106
	/* EEE */
107
108
109
110
111
	STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
	STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
	STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
	STMMAC_STAT(phy_eee_wakeup_error_n),
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
	/* Extended RDES status */
	STMMAC_STAT(ip_hdr_err),
	STMMAC_STAT(ip_payload_err),
	STMMAC_STAT(ip_csum_bypassed),
	STMMAC_STAT(ipv4_pkt_rcvd),
	STMMAC_STAT(ipv6_pkt_rcvd),
	STMMAC_STAT(rx_msg_type_ext_no_ptp),
	STMMAC_STAT(rx_msg_type_sync),
	STMMAC_STAT(rx_msg_type_follow_up),
	STMMAC_STAT(rx_msg_type_delay_req),
	STMMAC_STAT(rx_msg_type_delay_resp),
	STMMAC_STAT(rx_msg_type_pdelay_req),
	STMMAC_STAT(rx_msg_type_pdelay_resp),
	STMMAC_STAT(rx_msg_type_pdelay_follow_up),
	STMMAC_STAT(ptp_frame_type),
	STMMAC_STAT(ptp_ver),
	STMMAC_STAT(timestamp_dropped),
	STMMAC_STAT(av_pkt_rcvd),
	STMMAC_STAT(av_tagged_pkt_rcvd),
	STMMAC_STAT(vlan_tag_priority_val),
	STMMAC_STAT(l3_filter_match),
	STMMAC_STAT(l4_filter_match),
	STMMAC_STAT(l3_l4_filter_no_match),
135
136
137
138
	/* PCS */
	STMMAC_STAT(irq_pcs_ane_n),
	STMMAC_STAT(irq_pcs_link_n),
	STMMAC_STAT(irq_rgmii_n),
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
	/* DEBUG */
	STMMAC_STAT(mtl_tx_status_fifo_full),
	STMMAC_STAT(mtl_tx_fifo_not_empty),
	STMMAC_STAT(mmtl_fifo_ctrl),
	STMMAC_STAT(mtl_tx_fifo_read_ctrl_write),
	STMMAC_STAT(mtl_tx_fifo_read_ctrl_wait),
	STMMAC_STAT(mtl_tx_fifo_read_ctrl_read),
	STMMAC_STAT(mtl_tx_fifo_read_ctrl_idle),
	STMMAC_STAT(mac_tx_in_pause),
	STMMAC_STAT(mac_tx_frame_ctrl_xfer),
	STMMAC_STAT(mac_tx_frame_ctrl_idle),
	STMMAC_STAT(mac_tx_frame_ctrl_wait),
	STMMAC_STAT(mac_tx_frame_ctrl_pause),
	STMMAC_STAT(mac_gmii_tx_proto_engine),
	STMMAC_STAT(mtl_rx_fifo_fill_level_full),
	STMMAC_STAT(mtl_rx_fifo_fill_above_thresh),
	STMMAC_STAT(mtl_rx_fifo_fill_below_thresh),
	STMMAC_STAT(mtl_rx_fifo_fill_level_empty),
	STMMAC_STAT(mtl_rx_fifo_read_ctrl_flush),
	STMMAC_STAT(mtl_rx_fifo_read_ctrl_read_data),
	STMMAC_STAT(mtl_rx_fifo_read_ctrl_status),
	STMMAC_STAT(mtl_rx_fifo_read_ctrl_idle),
	STMMAC_STAT(mtl_rx_fifo_ctrl_active),
	STMMAC_STAT(mac_rx_frame_ctrl_fifo),
	STMMAC_STAT(mac_gmii_rx_proto_engine),
Alexandre TORGUE's avatar
Alexandre TORGUE committed
164
165
166
	/* TSO */
	STMMAC_STAT(tx_tso_frames),
	STMMAC_STAT(tx_tso_nfrags),
167
168
169
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)

170
171
172
173
174
/* HW MAC Management counters (if supported) */
#define STMMAC_MMC_STAT(m)	\
	{ #m, FIELD_SIZEOF(struct stmmac_counters, m),	\
	offsetof(struct stmmac_priv, mmc.m)}

175
static const struct stmmac_stats stmmac_mmc[] = {
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	STMMAC_MMC_STAT(mmc_tx_octetcount_gb),
	STMMAC_MMC_STAT(mmc_tx_framecount_gb),
	STMMAC_MMC_STAT(mmc_tx_broadcastframe_g),
	STMMAC_MMC_STAT(mmc_tx_multicastframe_g),
	STMMAC_MMC_STAT(mmc_tx_64_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_65_to_127_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_128_to_255_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_256_to_511_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_512_to_1023_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_1024_to_max_octets_gb),
	STMMAC_MMC_STAT(mmc_tx_unicast_gb),
	STMMAC_MMC_STAT(mmc_tx_multicast_gb),
	STMMAC_MMC_STAT(mmc_tx_broadcast_gb),
	STMMAC_MMC_STAT(mmc_tx_underflow_error),
	STMMAC_MMC_STAT(mmc_tx_singlecol_g),
	STMMAC_MMC_STAT(mmc_tx_multicol_g),
	STMMAC_MMC_STAT(mmc_tx_deferred),
	STMMAC_MMC_STAT(mmc_tx_latecol),
	STMMAC_MMC_STAT(mmc_tx_exesscol),
	STMMAC_MMC_STAT(mmc_tx_carrier_error),
	STMMAC_MMC_STAT(mmc_tx_octetcount_g),
	STMMAC_MMC_STAT(mmc_tx_framecount_g),
	STMMAC_MMC_STAT(mmc_tx_excessdef),
	STMMAC_MMC_STAT(mmc_tx_pause_frame),
	STMMAC_MMC_STAT(mmc_tx_vlan_frame_g),
	STMMAC_MMC_STAT(mmc_rx_framecount_gb),
	STMMAC_MMC_STAT(mmc_rx_octetcount_gb),
	STMMAC_MMC_STAT(mmc_rx_octetcount_g),
	STMMAC_MMC_STAT(mmc_rx_broadcastframe_g),
	STMMAC_MMC_STAT(mmc_rx_multicastframe_g),
206
	STMMAC_MMC_STAT(mmc_rx_crc_error),
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
	STMMAC_MMC_STAT(mmc_rx_align_error),
	STMMAC_MMC_STAT(mmc_rx_run_error),
	STMMAC_MMC_STAT(mmc_rx_jabber_error),
	STMMAC_MMC_STAT(mmc_rx_undersize_g),
	STMMAC_MMC_STAT(mmc_rx_oversize_g),
	STMMAC_MMC_STAT(mmc_rx_64_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_65_to_127_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_128_to_255_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_256_to_511_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_512_to_1023_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_1024_to_max_octets_gb),
	STMMAC_MMC_STAT(mmc_rx_unicast_g),
	STMMAC_MMC_STAT(mmc_rx_length_error),
	STMMAC_MMC_STAT(mmc_rx_autofrangetype),
	STMMAC_MMC_STAT(mmc_rx_pause_frames),
	STMMAC_MMC_STAT(mmc_rx_fifo_overflow),
	STMMAC_MMC_STAT(mmc_rx_vlan_frames_gb),
	STMMAC_MMC_STAT(mmc_rx_watchdog_error),
	STMMAC_MMC_STAT(mmc_rx_ipc_intr_mask),
	STMMAC_MMC_STAT(mmc_rx_ipc_intr),
	STMMAC_MMC_STAT(mmc_rx_ipv4_gd),
	STMMAC_MMC_STAT(mmc_rx_ipv4_hderr),
	STMMAC_MMC_STAT(mmc_rx_ipv4_nopay),
	STMMAC_MMC_STAT(mmc_rx_ipv4_frag),
	STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl),
	STMMAC_MMC_STAT(mmc_rx_ipv4_gd_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv4_hderr_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv4_nopay_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv4_frag_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv6_gd_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv6_hderr_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv6_nopay_octets),
	STMMAC_MMC_STAT(mmc_rx_ipv6_gd),
	STMMAC_MMC_STAT(mmc_rx_ipv6_hderr),
	STMMAC_MMC_STAT(mmc_rx_ipv6_nopay),
	STMMAC_MMC_STAT(mmc_rx_udp_gd),
	STMMAC_MMC_STAT(mmc_rx_udp_err),
	STMMAC_MMC_STAT(mmc_rx_tcp_gd),
	STMMAC_MMC_STAT(mmc_rx_tcp_err),
	STMMAC_MMC_STAT(mmc_rx_icmp_gd),
	STMMAC_MMC_STAT(mmc_rx_icmp_err),
	STMMAC_MMC_STAT(mmc_rx_udp_gd_octets),
	STMMAC_MMC_STAT(mmc_rx_udp_err_octets),
	STMMAC_MMC_STAT(mmc_rx_tcp_gd_octets),
	STMMAC_MMC_STAT(mmc_rx_tcp_err_octets),
	STMMAC_MMC_STAT(mmc_rx_icmp_gd_octets),
	STMMAC_MMC_STAT(mmc_rx_icmp_err_octets),
};
256
#define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_mmc)
257

258
259
static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
				      struct ethtool_drvinfo *info)
260
261
262
{
	struct stmmac_priv *priv = netdev_priv(dev);

263
	if (priv->plat->has_gmac)
264
		strlcpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver));
265
	else
266
267
		strlcpy(info->driver, MAC100_ETHTOOL_NAME,
			sizeof(info->driver));
268

269
	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
270
271
}

272
273
static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
					     struct ethtool_link_ksettings *cmd)
274
275
{
	struct stmmac_priv *priv = netdev_priv(dev);
276
	struct phy_device *phy = dev->phydev;
277
	int rc;
278

279
280
	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
	    priv->hw->pcs & STMMAC_PCS_SGMII) {
281
		struct rgmii_adv adv;
282
		u32 supported, advertising, lp_advertising;
283
284

		if (!priv->xstats.pcs_link) {
285
286
			cmd->base.speed = SPEED_UNKNOWN;
			cmd->base.duplex = DUPLEX_UNKNOWN;
287
288
			return 0;
		}
289
		cmd->base.duplex = priv->xstats.pcs_duplex;
290

291
		cmd->base.speed = priv->xstats.pcs_speed;
292
293

		/* Get and convert ADV/LP_ADV from the HW AN registers */
294
		if (!priv->hw->mac->pcs_get_adv_lp)
295
296
			return -EOPNOTSUPP;	/* should never happen indeed */

297
		priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv);
Pavel Machek's avatar
Pavel Machek committed
298

299
300
		/* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */

301
302
303
304
305
306
307
		ethtool_convert_link_mode_to_legacy_u32(
			&supported, cmd->link_modes.supported);
		ethtool_convert_link_mode_to_legacy_u32(
			&advertising, cmd->link_modes.advertising);
		ethtool_convert_link_mode_to_legacy_u32(
			&lp_advertising, cmd->link_modes.lp_advertising);

308
		if (adv.pause & STMMAC_PCS_PAUSE)
309
			advertising |= ADVERTISED_Pause;
310
		if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
311
			advertising |= ADVERTISED_Asym_Pause;
312
		if (adv.lp_pause & STMMAC_PCS_PAUSE)
313
			lp_advertising |= ADVERTISED_Pause;
314
		if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
315
			lp_advertising |= ADVERTISED_Asym_Pause;
316
317

		/* Reg49[3] always set because ANE is always supported */
318
319
320
321
		cmd->base.autoneg = ADVERTISED_Autoneg;
		supported |= SUPPORTED_Autoneg;
		advertising |= ADVERTISED_Autoneg;
		lp_advertising |= ADVERTISED_Autoneg;
322
323

		if (adv.duplex) {
324
325
326
327
328
329
			supported |= (SUPPORTED_1000baseT_Full |
				      SUPPORTED_100baseT_Full |
				      SUPPORTED_10baseT_Full);
			advertising |= (ADVERTISED_1000baseT_Full |
					ADVERTISED_100baseT_Full |
					ADVERTISED_10baseT_Full);
330
		} else {
331
332
333
334
335
336
			supported |= (SUPPORTED_1000baseT_Half |
				      SUPPORTED_100baseT_Half |
				      SUPPORTED_10baseT_Half);
			advertising |= (ADVERTISED_1000baseT_Half |
					ADVERTISED_100baseT_Half |
					ADVERTISED_10baseT_Half);
337
338
		}
		if (adv.lp_duplex)
339
340
341
			lp_advertising |= (ADVERTISED_1000baseT_Full |
					   ADVERTISED_100baseT_Full |
					   ADVERTISED_10baseT_Full);
342
		else
343
344
345
346
347
348
349
350
351
352
353
			lp_advertising |= (ADVERTISED_1000baseT_Half |
					   ADVERTISED_100baseT_Half |
					   ADVERTISED_10baseT_Half);
		cmd->base.port = PORT_OTHER;

		ethtool_convert_legacy_u32_to_link_mode(
			cmd->link_modes.supported, supported);
		ethtool_convert_legacy_u32_to_link_mode(
			cmd->link_modes.advertising, advertising);
		ethtool_convert_legacy_u32_to_link_mode(
			cmd->link_modes.lp_advertising, lp_advertising);
354
355
356
357

		return 0;
	}

358
359
360
361
362
363
364
365
366
367
	if (phy == NULL) {
		pr_err("%s: %s: PHY is not registered\n",
		       __func__, dev->name);
		return -ENODEV;
	}
	if (!netif_running(dev)) {
		pr_err("%s: interface is disabled: we cannot track "
		"link speed / duplex setting\n", dev->name);
		return -EBUSY;
	}
368
	rc = phy_ethtool_ksettings_get(phy, cmd);
369
370
371
	return rc;
}

372
373
374
static int
stmmac_ethtool_set_link_ksettings(struct net_device *dev,
				  const struct ethtool_link_ksettings *cmd)
375
376
{
	struct stmmac_priv *priv = netdev_priv(dev);
377
	struct phy_device *phy = dev->phydev;
378
379
	int rc;

380
381
	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
	    priv->hw->pcs & STMMAC_PCS_SGMII) {
382
383
384
		u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;

		/* Only support ANE */
385
		if (cmd->base.autoneg != AUTONEG_ENABLE)
386
387
			return -EINVAL;

Pavel Machek's avatar
Pavel Machek committed
388
		mask &= (ADVERTISED_1000baseT_Half |
389
390
391
392
393
394
			ADVERTISED_1000baseT_Full |
			ADVERTISED_100baseT_Half |
			ADVERTISED_100baseT_Full |
			ADVERTISED_10baseT_Half |
			ADVERTISED_10baseT_Full);

Pavel Machek's avatar
Pavel Machek committed
395
		spin_lock(&priv->lock);
396
397

		if (priv->hw->mac->pcs_ctrl_ane)
398
399
			priv->hw->mac->pcs_ctrl_ane(priv->ioaddr, 1,
						    priv->hw->ps, 0);
400

Pavel Machek's avatar
Pavel Machek committed
401
		spin_unlock(&priv->lock);
402
403
404
405

		return 0;
	}

406
	spin_lock(&priv->lock);
407
	rc = phy_ethtool_ksettings_set(phy, cmd);
408
409
410
411
412
	spin_unlock(&priv->lock);

	return rc;
}

413
static u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
414
415
416
417
418
{
	struct stmmac_priv *priv = netdev_priv(dev);
	return priv->msg_enable;
}

419
static void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
420
421
422
423
424
425
{
	struct stmmac_priv *priv = netdev_priv(dev);
	priv->msg_enable = level;

}

426
static int stmmac_check_if_running(struct net_device *dev)
427
428
429
430
431
432
{
	if (!netif_running(dev))
		return -EBUSY;
	return 0;
}

433
static int stmmac_ethtool_get_regs_len(struct net_device *dev)
434
435
436
437
{
	return REG_SPACE_SIZE;
}

438
static void stmmac_ethtool_gregs(struct net_device *dev,
439
440
441
442
443
444
445
446
447
			  struct ethtool_regs *regs, void *space)
{
	int i;
	u32 *reg_space = (u32 *) space;

	struct stmmac_priv *priv = netdev_priv(dev);

	memset(reg_space, 0x0, REG_SPACE_SIZE);

448
	if (!priv->plat->has_gmac) {
449
450
		/* MAC registers */
		for (i = 0; i < 12; i++)
451
			reg_space[i] = readl(priv->ioaddr + (i * 4));
452
453
454
		/* DMA registers */
		for (i = 0; i < 9; i++)
			reg_space[i + 12] =
455
456
457
			    readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
		reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR);
		reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR);
458
459
460
	} else {
		/* MAC registers */
		for (i = 0; i < 55; i++)
461
			reg_space[i] = readl(priv->ioaddr + (i * 4));
462
463
464
		/* DMA registers */
		for (i = 0; i < 22; i++)
			reg_space[i + 55] =
465
			    readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
466
467
468
469
470
471
472
473
474
475
476
	}
}

static void
stmmac_get_pauseparam(struct net_device *netdev,
		      struct ethtool_pauseparam *pause)
{
	struct stmmac_priv *priv = netdev_priv(netdev);

	pause->rx_pause = 0;
	pause->tx_pause = 0;
477

478
	if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
479
480
481
482
483
484
485
		struct rgmii_adv adv_lp;

		pause->autoneg = 1;
		priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv_lp);
		if (!adv_lp.pause)
			return;
	} else {
486
487
		if (!(netdev->phydev->supported & SUPPORTED_Pause) ||
		    !(netdev->phydev->supported & SUPPORTED_Asym_Pause))
488
489
490
			return;
	}

491
	pause->autoneg = netdev->phydev->autoneg;
492
493
494
495
496
497
498
499
500
501
502
503
504

	if (priv->flow_ctrl & FLOW_RX)
		pause->rx_pause = 1;
	if (priv->flow_ctrl & FLOW_TX)
		pause->tx_pause = 1;

}

static int
stmmac_set_pauseparam(struct net_device *netdev,
		      struct ethtool_pauseparam *pause)
{
	struct stmmac_priv *priv = netdev_priv(netdev);
505
	struct phy_device *phy = netdev->phydev;
506
507
	int new_pause = FLOW_OFF;

508
	if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
509
510
511
512
513
514
515
516
517
518
519
		struct rgmii_adv adv_lp;

		pause->autoneg = 1;
		priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv_lp);
		if (!adv_lp.pause)
			return -EOPNOTSUPP;
	} else {
		if (!(phy->supported & SUPPORTED_Pause) ||
		    !(phy->supported & SUPPORTED_Asym_Pause))
			return -EOPNOTSUPP;
	}
520

521
522
523
524
525
526
	if (pause->rx_pause)
		new_pause |= FLOW_RX;
	if (pause->tx_pause)
		new_pause |= FLOW_TX;

	priv->flow_ctrl = new_pause;
527
	phy->autoneg = pause->autoneg;
528

529
	if (phy->autoneg) {
530
		if (netif_running(netdev))
531
532
533
534
535
536
			return phy_start_aneg(phy);
	}

	priv->hw->mac->flow_ctrl(priv->hw, phy->duplex, priv->flow_ctrl,
				 priv->pause);
	return 0;
537
538
539
540
541
542
}

static void stmmac_get_ethtool_stats(struct net_device *dev,
				 struct ethtool_stats *dummy, u64 *data)
{
	struct stmmac_priv *priv = netdev_priv(dev);
543
	int i, j = 0;
544

545
	/* Update the DMA HW counters for dwmac10/100 */
Alexandre TORGUE's avatar
Alexandre TORGUE committed
546
	if (priv->hw->dma->dma_diagnostic_fr)
547
548
549
550
551
		priv->hw->dma->dma_diagnostic_fr(&dev->stats,
						 (void *) &priv->xstats,
						 priv->ioaddr);
	else {
		/* If supported, for new GMAC chips expose the MMC counters */
552
		if (priv->dma_cap.rmon) {
553
			dwmac_mmc_read(priv->mmcaddr, &priv->mmc);
554

555
556
557
			for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
				char *p;
				p = (char *)priv + stmmac_mmc[i].stat_offset;
558

559
560
561
562
				data[j++] = (stmmac_mmc[i].sizeof_stat ==
					     sizeof(u64)) ? (*(u64 *)p) :
					     (*(u32 *)p);
			}
563
		}
564
		if (priv->eee_enabled) {
565
			int val = phy_get_eee_err(dev->phydev);
566
567
568
			if (val)
				priv->xstats.phy_eee_wakeup_error_n = val;
		}
569
570
571
572
573

		if ((priv->hw->mac->debug) &&
		    (priv->synopsys_id >= DWMAC_CORE_3_50))
			priv->hw->mac->debug(priv->ioaddr,
					     (void *)&priv->xstats);
574
	}
575
576
	for (i = 0; i < STMMAC_STATS_LEN; i++) {
		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
577
578
		data[j++] = (stmmac_gstrings_stats[i].sizeof_stat ==
			     sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
579
580
581
582
583
	}
}

static int stmmac_get_sset_count(struct net_device *netdev, int sset)
{
584
585
586
	struct stmmac_priv *priv = netdev_priv(netdev);
	int len;

587
588
	switch (sset) {
	case ETH_SS_STATS:
589
590
		len = STMMAC_STATS_LEN;

591
		if (priv->dma_cap.rmon)
592
593
594
			len += STMMAC_MMC_STATS_LEN;

		return len;
595
596
597
598
599
600
601
602
603
	default:
		return -EOPNOTSUPP;
	}
}

static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
	int i;
	u8 *p = data;
604
	struct stmmac_priv *priv = netdev_priv(dev);
605
606
607

	switch (stringset) {
	case ETH_SS_STATS:
608
		if (priv->dma_cap.rmon)
609
			for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
610
				memcpy(p, stmmac_mmc[i].stat_string,
611
612
613
				       ETH_GSTRING_LEN);
				p += ETH_GSTRING_LEN;
			}
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
		for (i = 0; i < STMMAC_STATS_LEN; i++) {
			memcpy(p, stmmac_gstrings_stats[i].stat_string,
				ETH_GSTRING_LEN);
			p += ETH_GSTRING_LEN;
		}
		break;
	default:
		WARN_ON(1);
		break;
	}
}

/* Currently only support WOL through Magic packet. */
static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
	struct stmmac_priv *priv = netdev_priv(dev);

	spin_lock_irq(&priv->lock);
632
	if (device_can_wakeup(priv->device)) {
633
		wol->supported = WAKE_MAGIC | WAKE_UCAST;
634
635
636
637
638
639
640
641
		wol->wolopts = priv->wolopts;
	}
	spin_unlock_irq(&priv->lock);
}

static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
	struct stmmac_priv *priv = netdev_priv(dev);
642
	u32 support = WAKE_MAGIC | WAKE_UCAST;
643

644
645
646
647
648
649
	/* By default almost all GMAC devices support the WoL via
	 * magic frame but we can disable it if the HW capability
	 * register shows no support for pmt_magic_frame. */
	if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
		wol->wolopts &= ~WAKE_MAGIC;

650
	if (!device_can_wakeup(priv->device))
651
652
653
654
655
		return -EINVAL;

	if (wol->wolopts & ~support)
		return -EINVAL;

656
657
	if (wol->wolopts) {
		pr_info("stmmac: wakeup enable\n");
658
		device_set_wakeup_enable(priv->device, 1);
659
		enable_irq_wake(priv->wol_irq);
660
661
	} else {
		device_set_wakeup_enable(priv->device, 0);
662
		disable_irq_wake(priv->wol_irq);
663
	}
664
665
666
667
668
669
670
671

	spin_lock_irq(&priv->lock);
	priv->wolopts = wol->wolopts;
	spin_unlock_irq(&priv->lock);

	return 0;
}

672
673
674
675
676
677
678
679
680
681
682
683
static int stmmac_ethtool_op_get_eee(struct net_device *dev,
				     struct ethtool_eee *edata)
{
	struct stmmac_priv *priv = netdev_priv(dev);

	if (!priv->dma_cap.eee)
		return -EOPNOTSUPP;

	edata->eee_enabled = priv->eee_enabled;
	edata->eee_active = priv->eee_active;
	edata->tx_lpi_timer = priv->tx_lpi_timer;

684
	return phy_ethtool_get_eee(dev->phydev, edata);
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
}

static int stmmac_ethtool_op_set_eee(struct net_device *dev,
				     struct ethtool_eee *edata)
{
	struct stmmac_priv *priv = netdev_priv(dev);

	priv->eee_enabled = edata->eee_enabled;

	if (!priv->eee_enabled)
		stmmac_disable_eee_mode(priv);
	else {
		/* We are asking for enabling the EEE but it is safe
		 * to verify all by invoking the eee_init function.
		 * In case of failure it will return an error.
		 */
		priv->eee_enabled = stmmac_eee_init(priv);
		if (!priv->eee_enabled)
			return -EOPNOTSUPP;

		/* Do not change tx_lpi_timer in case of failure */
		priv->tx_lpi_timer = edata->tx_lpi_timer;
	}

709
	return phy_ethtool_set_eee(dev->phydev, edata);
710
711
}

712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
{
	unsigned long clk = clk_get_rate(priv->stmmac_clk);

	if (!clk)
		return 0;

	return (usec * (clk / 1000000)) / 256;
}

static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
{
	unsigned long clk = clk_get_rate(priv->stmmac_clk);

	if (!clk)
		return 0;

	return (riwt * 256) / (clk / 1000000);
}

static int stmmac_get_coalesce(struct net_device *dev,
			       struct ethtool_coalesce *ec)
{
	struct stmmac_priv *priv = netdev_priv(dev);

	ec->tx_coalesce_usecs = priv->tx_coal_timer;
	ec->tx_max_coalesced_frames = priv->tx_coal_frames;

	if (priv->use_riwt)
		ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv);

	return 0;
}

static int stmmac_set_coalesce(struct net_device *dev,
			       struct ethtool_coalesce *ec)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	unsigned int rx_riwt;

	/* Check not supported parameters  */
	if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) ||
	    (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
	    (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
	    (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) ||
	    (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) ||
	    (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) ||
	    (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) ||
	    (ec->rx_max_coalesced_frames_high) ||
	    (ec->tx_max_coalesced_frames_irq) ||
	    (ec->stats_block_coalesce_usecs) ||
	    (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval))
		return -EOPNOTSUPP;

	if (ec->rx_coalesce_usecs == 0)
		return -EINVAL;

	if ((ec->tx_coalesce_usecs == 0) &&
	    (ec->tx_max_coalesced_frames == 0))
		return -EINVAL;

773
	if ((ec->tx_coalesce_usecs > STMMAC_MAX_COAL_TX_TICK) ||
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
	    (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
		return -EINVAL;

	rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv);

	if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT))
		return -EINVAL;
	else if (!priv->use_riwt)
		return -EOPNOTSUPP;

	/* Only copy relevant parameters, ignore all others. */
	priv->tx_coal_frames = ec->tx_max_coalesced_frames;
	priv->tx_coal_timer = ec->tx_coalesce_usecs;
	priv->rx_riwt = rx_riwt;
	priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt);

	return 0;
}

793
794
795
796
797
static int stmmac_get_ts_info(struct net_device *dev,
			      struct ethtool_ts_info *info)
{
	struct stmmac_priv *priv = netdev_priv(dev);

798
	if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) {
799

800
801
802
		info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
					SOF_TIMESTAMPING_TX_HARDWARE |
					SOF_TIMESTAMPING_RX_SOFTWARE |
803
					SOF_TIMESTAMPING_RX_HARDWARE |
804
					SOF_TIMESTAMPING_SOFTWARE |
805
806
					SOF_TIMESTAMPING_RAW_HARDWARE;

807
808
809
		if (priv->ptp_clock)
			info->phc_index = ptp_clock_index(priv->ptp_clock);

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
		info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);

		info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
				    (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
				    (1 << HWTSTAMP_FILTER_ALL));
		return 0;
	} else
		return ethtool_op_get_ts_info(dev, info);
}

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
static int stmmac_get_tunable(struct net_device *dev,
			      const struct ethtool_tunable *tuna, void *data)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	int ret = 0;

	switch (tuna->id) {
	case ETHTOOL_RX_COPYBREAK:
		*(u32 *)data = priv->rx_copybreak;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

static int stmmac_set_tunable(struct net_device *dev,
			      const struct ethtool_tunable *tuna,
			      const void *data)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	int ret = 0;

	switch (tuna->id) {
	case ETHTOOL_RX_COPYBREAK:
		priv->rx_copybreak = *(u32 *)data;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

865
static const struct ethtool_ops stmmac_ethtool_ops = {
866
867
868
869
870
871
872
	.begin = stmmac_check_if_running,
	.get_drvinfo = stmmac_ethtool_getdrvinfo,
	.get_msglevel = stmmac_ethtool_getmsglevel,
	.set_msglevel = stmmac_ethtool_setmsglevel,
	.get_regs = stmmac_ethtool_gregs,
	.get_regs_len = stmmac_ethtool_get_regs_len,
	.get_link = ethtool_op_get_link,
873
	.nway_reset = phy_ethtool_nway_reset,
874
875
876
877
878
879
	.get_pauseparam = stmmac_get_pauseparam,
	.set_pauseparam = stmmac_set_pauseparam,
	.get_ethtool_stats = stmmac_get_ethtool_stats,
	.get_strings = stmmac_get_strings,
	.get_wol = stmmac_get_wol,
	.set_wol = stmmac_set_wol,
880
881
	.get_eee = stmmac_ethtool_op_get_eee,
	.set_eee = stmmac_ethtool_op_set_eee,
882
	.get_sset_count	= stmmac_get_sset_count,
883
	.get_ts_info = stmmac_get_ts_info,
884
885
	.get_coalesce = stmmac_get_coalesce,
	.set_coalesce = stmmac_set_coalesce,
886
887
	.get_tunable = stmmac_get_tunable,
	.set_tunable = stmmac_set_tunable,
888
889
	.get_link_ksettings = stmmac_ethtool_get_link_ksettings,
	.set_link_ksettings = stmmac_ethtool_set_link_ksettings,
890
891
892
893
};

void stmmac_set_ethtool_ops(struct net_device *netdev)
{
894
	netdev->ethtool_ops = &stmmac_ethtool_ops;
895
}