aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2012-12-05 03:40:59 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-01-18 07:54:49 -0500
commit203e41514a557b71c4c42b4bb2912b56fa0c2fdc (patch)
tree956d6ab42a9eee23a0e0f9ec391b836ba7aa2b4c
parent887c95cc1da53f66a5890fdeab13414613010097 (diff)
e1000e: add ethtool .get_eee/.set_eee
Add the ability to query and set Energy Efficient Ethernet parameters via ethtool for applicable devices. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h30
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c134
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c24
5 files changed, 167 insertions, 23 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index 7326ea2fef8f..3041a54e3a61 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -383,6 +383,9 @@
383 383
384#define E1000_KABGTXD_BGSQLBIAS 0x00050000 384#define E1000_KABGTXD_BGSQLBIAS 0x00050000
385 385
386/* Low Power IDLE Control */
387#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */
388
386/* PBA constants */ 389/* PBA constants */
387#define E1000_PBA_8K 0x0008 /* 8KB */ 390#define E1000_PBA_8K 0x0008 /* 8KB */
388#define E1000_PBA_16K 0x0010 /* 16KB */ 391#define E1000_PBA_16K 0x0010 /* 16KB */
@@ -799,6 +802,33 @@
799/* BME1000 PHY Specific Control Register */ 802/* BME1000 PHY Specific Control Register */
800#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ 803#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
801 804
805/* PHY Low Power Idle Control */
806#define I82579_LPI_CTRL PHY_REG(772, 20)
807#define I82579_LPI_CTRL_100_ENABLE 0x2000
808#define I82579_LPI_CTRL_1000_ENABLE 0x4000
809#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
810#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
811
812/* Extended Management Interface (EMI) Registers */
813#define I82579_EMI_ADDR 0x10
814#define I82579_EMI_DATA 0x11
815#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
816#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */
817#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
818#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
819#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
820#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */
821#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */
822#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
823#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
824#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
825#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
826#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */
827#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
828#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
829
830#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */
831#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */
802 832
803#define PHY_PAGE_SHIFT 5 833#define PHY_PAGE_SHIFT 5
804#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ 834#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 3f8bbc31795c..b89b181da7b1 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -659,6 +659,7 @@ extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
659extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); 659extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
660extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); 660extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
661extern bool e1000_check_phy_82574(struct e1000_hw *hw); 661extern bool e1000_check_phy_82574(struct e1000_hw *hw);
662extern s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data);
662 663
663static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) 664static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
664{ 665{
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 2225603a8a28..636ba09ca6fb 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -35,6 +35,7 @@
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/vmalloc.h> 37#include <linux/vmalloc.h>
38#include <linux/mdio.h>
38 39
39#include "e1000.h" 40#include "e1000.h"
40 41
@@ -2050,6 +2051,137 @@ static int e1000_get_rxnfc(struct net_device *netdev,
2050 } 2051 }
2051} 2052}
2052 2053
2054static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
2055{
2056 struct e1000_adapter *adapter = netdev_priv(netdev);
2057 struct e1000_hw *hw = &adapter->hw;
2058 u16 cap_addr, adv_addr, lpa_addr, pcs_stat_addr, phy_data, lpi_ctrl;
2059 u32 status, ret_val;
2060
2061 if (!(adapter->flags & FLAG_IS_ICH) ||
2062 !(adapter->flags2 & FLAG2_HAS_EEE))
2063 return -EOPNOTSUPP;
2064
2065 switch (hw->phy.type) {
2066 case e1000_phy_82579:
2067 cap_addr = I82579_EEE_CAPABILITY;
2068 adv_addr = I82579_EEE_ADVERTISEMENT;
2069 lpa_addr = I82579_EEE_LP_ABILITY;
2070 pcs_stat_addr = I82579_EEE_PCS_STATUS;
2071 break;
2072 case e1000_phy_i217:
2073 cap_addr = I217_EEE_CAPABILITY;
2074 adv_addr = I217_EEE_ADVERTISEMENT;
2075 lpa_addr = I217_EEE_LP_ABILITY;
2076 pcs_stat_addr = I217_EEE_PCS_STATUS;
2077 break;
2078 default:
2079 return -EOPNOTSUPP;
2080 }
2081
2082 ret_val = hw->phy.ops.acquire(hw);
2083 if (ret_val)
2084 return -EBUSY;
2085
2086 /* EEE Capability */
2087 ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data);
2088 if (ret_val)
2089 goto release;
2090 edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data);
2091
2092 /* EEE Advertised */
2093 ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &phy_data);
2094 if (ret_val)
2095 goto release;
2096 edata->advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
2097
2098 /* EEE Link Partner Advertised */
2099 ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data);
2100 if (ret_val)
2101 goto release;
2102 edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
2103
2104 /* EEE PCS Status */
2105 ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data);
2106 if (hw->phy.type == e1000_phy_82579)
2107 phy_data <<= 8;
2108
2109release:
2110 hw->phy.ops.release(hw);
2111 if (ret_val)
2112 return -ENODATA;
2113
2114 e1e_rphy(hw, I82579_LPI_CTRL, &lpi_ctrl);
2115 status = er32(STATUS);
2116
2117 /* Result of the EEE auto negotiation - there is no register that
2118 * has the status of the EEE negotiation so do a best-guess based
2119 * on whether both Tx and Rx LPI indications have been received or
2120 * base it on the link speed, the EEE advertised speeds on both ends
2121 * and the speeds on which EEE is enabled locally.
2122 */
2123 if (((phy_data & E1000_EEE_TX_LPI_RCVD) &&
2124 (phy_data & E1000_EEE_RX_LPI_RCVD)) ||
2125 ((status & E1000_STATUS_SPEED_100) &&
2126 (edata->advertised & ADVERTISED_100baseT_Full) &&
2127 (edata->lp_advertised & ADVERTISED_100baseT_Full) &&
2128 (lpi_ctrl & I82579_LPI_CTRL_100_ENABLE)) ||
2129 ((status & E1000_STATUS_SPEED_1000) &&
2130 (edata->advertised & ADVERTISED_1000baseT_Full) &&
2131 (edata->lp_advertised & ADVERTISED_1000baseT_Full) &&
2132 (lpi_ctrl & I82579_LPI_CTRL_1000_ENABLE)))
2133 edata->eee_active = true;
2134
2135 edata->eee_enabled = !hw->dev_spec.ich8lan.eee_disable;
2136 edata->tx_lpi_enabled = true;
2137 edata->tx_lpi_timer = er32(LPIC) >> E1000_LPIC_LPIET_SHIFT;
2138
2139 return 0;
2140}
2141
2142static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
2143{
2144 struct e1000_adapter *adapter = netdev_priv(netdev);
2145 struct e1000_hw *hw = &adapter->hw;
2146 struct ethtool_eee eee_curr;
2147 s32 ret_val;
2148
2149 if (!(adapter->flags & FLAG_IS_ICH) ||
2150 !(adapter->flags2 & FLAG2_HAS_EEE))
2151 return -EOPNOTSUPP;
2152
2153 ret_val = e1000e_get_eee(netdev, &eee_curr);
2154 if (ret_val)
2155 return ret_val;
2156
2157 if (eee_curr.advertised != edata->advertised) {
2158 e_err("Setting EEE advertisement is not supported\n");
2159 return -EINVAL;
2160 }
2161
2162 if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
2163 e_err("Setting EEE tx-lpi is not supported\n");
2164 return -EINVAL;
2165 }
2166
2167 if (eee_curr.tx_lpi_timer != edata->tx_lpi_timer) {
2168 e_err("Setting EEE Tx LPI timer is not supported\n");
2169 return -EINVAL;
2170 }
2171
2172 if (hw->dev_spec.ich8lan.eee_disable != !edata->eee_enabled) {
2173 hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;
2174
2175 /* reset the link */
2176 if (netif_running(netdev))
2177 e1000e_reinit_locked(adapter);
2178 else
2179 e1000e_reset(adapter);
2180 }
2181
2182 return 0;
2183}
2184
2053static const struct ethtool_ops e1000_ethtool_ops = { 2185static const struct ethtool_ops e1000_ethtool_ops = {
2054 .get_settings = e1000_get_settings, 2186 .get_settings = e1000_get_settings,
2055 .set_settings = e1000_set_settings, 2187 .set_settings = e1000_set_settings,
@@ -2078,6 +2210,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
2078 .set_coalesce = e1000_set_coalesce, 2210 .set_coalesce = e1000_set_coalesce,
2079 .get_rxnfc = e1000_get_rxnfc, 2211 .get_rxnfc = e1000_get_rxnfc,
2080 .get_ts_info = ethtool_op_get_ts_info, 2212 .get_ts_info = ethtool_op_get_ts_info,
2213 .get_eee = e1000e_get_eee,
2214 .set_eee = e1000e_set_eee,
2081}; 2215};
2082 2216
2083void e1000e_set_ethtool_ops(struct net_device *netdev) 2217void e1000e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 06239fe47db1..81afad5b80f2 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -62,6 +62,7 @@ enum e1e_registers {
62 E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */ 62 E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */
63 E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */ 63 E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */
64#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2)) 64#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2))
65 E1000_LPIC = 0x000FC, /* Low Power Idle Control - RW */
65 E1000_RCTL = 0x00100, /* Rx Control - RW */ 66 E1000_RCTL = 0x00100, /* Rx Control - RW */
66 E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */ 67 E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */
67 E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */ 68 E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 051dfda75fc0..3829f7fd1d97 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -148,28 +148,6 @@
148#define HV_PM_CTRL PHY_REG(770, 17) 148#define HV_PM_CTRL PHY_REG(770, 17)
149#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 149#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
150 150
151/* PHY Low Power Idle Control */
152#define I82579_LPI_CTRL PHY_REG(772, 20)
153#define I82579_LPI_CTRL_100_ENABLE 0x2000
154#define I82579_LPI_CTRL_1000_ENABLE 0x4000
155#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
156#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
157
158/* Extended Management Interface (EMI) Registers */
159#define I82579_EMI_ADDR 0x10
160#define I82579_EMI_DATA 0x11
161#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
162#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */
163#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
164#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
165#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
166#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
167#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
168#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
169#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
170#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
171#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
172
173/* Intel Rapid Start Technology Support */ 151/* Intel Rapid Start Technology Support */
174#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) 152#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70)
175#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 153#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
@@ -829,7 +807,7 @@ static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address,
829 * 807 *
830 * Assumes the SW/FW/HW Semaphore is already acquired. 808 * Assumes the SW/FW/HW Semaphore is already acquired.
831 **/ 809 **/
832static s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) 810s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
833{ 811{
834 return __e1000_access_emi_reg_locked(hw, addr, data, true); 812 return __e1000_access_emi_reg_locked(hw, addr, data, true);
835} 813}