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