1 /* 10G controller driver for Samsung SoCs
2  *
3  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
4  *		http://www.samsung.com
5  *
6  * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 
15 #include <linux/kernel.h>
16 #include <linux/netdevice.h>
17 #include <linux/phy.h>
18 
19 #include "sxgbe_common.h"
20 
21 struct sxgbe_stats {
22 	char stat_string[ETH_GSTRING_LEN];
23 	int sizeof_stat;
24 	int stat_offset;
25 };
26 
27 #define SXGBE_STAT(m)						\
28 {								\
29 	#m,							\
30 	FIELD_SIZEOF(struct sxgbe_extra_stats, m),		\
31 	offsetof(struct sxgbe_priv_data, xstats.m)		\
32 }
33 
34 static const struct sxgbe_stats sxgbe_gstrings_stats[] = {
35 	SXGBE_STAT(tx_lpi_entry_n),
36 	SXGBE_STAT(tx_lpi_exit_n),
37 	SXGBE_STAT(rx_lpi_entry_n),
38 	SXGBE_STAT(rx_lpi_exit_n),
39 	SXGBE_STAT(eee_wakeup_error_n),
40 };
41 #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats)
42 
43 static int sxgbe_get_eee(struct net_device *dev,
44 			 struct ethtool_eee *edata)
45 {
46 	struct sxgbe_priv_data *priv = netdev_priv(dev);
47 
48 	if (!priv->hw_cap.eee)
49 		return -EOPNOTSUPP;
50 
51 	edata->eee_enabled = priv->eee_enabled;
52 	edata->eee_active = priv->eee_active;
53 	edata->tx_lpi_timer = priv->tx_lpi_timer;
54 
55 	return phy_ethtool_get_eee(priv->phydev, edata);
56 }
57 
58 static int sxgbe_set_eee(struct net_device *dev,
59 			 struct ethtool_eee *edata)
60 {
61 	struct sxgbe_priv_data *priv = netdev_priv(dev);
62 
63 	priv->eee_enabled = edata->eee_enabled;
64 
65 	if (!priv->eee_enabled) {
66 		sxgbe_disable_eee_mode(priv);
67 	} else {
68 		/* We are asking for enabling the EEE but it is safe
69 		 * to verify all by invoking the eee_init function.
70 		 * In case of failure it will return an error.
71 		 */
72 		priv->eee_enabled = sxgbe_eee_init(priv);
73 		if (!priv->eee_enabled)
74 			return -EOPNOTSUPP;
75 
76 		/* Do not change tx_lpi_timer in case of failure */
77 		priv->tx_lpi_timer = edata->tx_lpi_timer;
78 	}
79 
80 	return phy_ethtool_set_eee(priv->phydev, edata);
81 }
82 
83 static const struct ethtool_ops sxgbe_ethtool_ops = {
84 	.get_eee = sxgbe_get_eee,
85 	.set_eee = sxgbe_set_eee,
86 };
87 
88 void sxgbe_set_ethtool_ops(struct net_device *netdev)
89 {
90 	SET_ETHTOOL_OPS(netdev, &sxgbe_ethtool_ops);
91 }
92