[U-Boot] [PATCH 2/2] net: phy: at803x: Address packet drops at low traffic rate due to SmartEEE feature

Vladimir Oltean vladimir.oltean at nxp.com
Tue Dec 18 22:36:56 UTC 2018


* According to the AR8031 and AR8035 datasheets, smartEEE mode
  (active by default) makes the PHY enter sleep after a configurable
  idle time. It does this autonomously, without LPI (Low Power Idle)
  signals coming from MAC. AR8021 does not appear to support this.
* This patch allows disabling the SmartEEE feature of above PHYs.
* Tested with ping (default of 1 second interval) over back-to-back
  RGMII between 2 boards having AR8035 at both ends:
    - Without SmartEEE:
  225 packets transmitted, 145 received, 35% packet loss, time 229334ms
    - With SmartEEE:
  144 packets transmitted, 144 received, 0% packet loss, time 146378ms

Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
---
 drivers/net/phy/Kconfig   | 21 +++++++++++++++++++++
 drivers/net/phy/atheros.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3dc0822..6abe8c5 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -94,6 +94,27 @@ config PHY_AQUANTIA_FW_NAME
 config PHY_ATHEROS
 	bool "Atheros Ethernet PHYs support"
 
+config PHY_ATHEROS_SMART_EEE
+	depends on PHY_ATHEROS
+	default y
+	tristate "SmartEEE feature for Atheros PHYs"
+	help
+	  Enables the Atheros SmartEEE feature (not IEEE 802.3az). When 2 PHYs
+	  which support this feature are connected back-to-back, they may
+	  negotiate a low-power sleep mode autonomously, without the Ethernet
+	  controller's knowledge. This setting may cause issues under 2 known
+	  circumstances (both noticed at low traffic rates):
+	    - If the voltage rails on the PHY are unstable, then the PHY can
+	      actually reset as it enters the low power state. This means that
+	      the frames it is supposed to buffer until it wakes up are going
+	      to be dropped instead.
+	    - If 1588/PTP synchronization is the only traffic source over this
+	      PHY, the delays caused by the sleep/wakeup time are going to add
+	      to the synchronization error between the master and the slave.
+	  Default y, which means that the PHY's out-of-reset state is not
+	  changed (SmartEEE active). To work around the issues described
+	  above, change to n.
+
 config PHY_BROADCOM
 	bool "Broadcom Ethernet PHYs support"
 
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 3783d15..a3c84fd 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -5,6 +5,7 @@
  * Copyright 2011, 2013 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <linux/bitops.h>
 #include <common.h>
 #include <phy.h>
 
@@ -17,6 +18,23 @@
 #define AR803x_DEBUG_REG_0		0x0
 #define AR803x_RGMII_RX_CLK_DLY		0x8000
 
+#define AR803X_LPI_EN			BIT(8)
+
+static void ar803x_enable_smart_eee(struct phy_device *phydev, bool on)
+{
+	int value;
+
+	/* 5.1.11 Smart_eee control3 */
+	value = phy_read_mmd_indirect(phydev, 0x805D, MDIO_MMD_PCS,
+				      MDIO_DEVAD_NONE);
+	if (on)
+		value |= AR803X_LPI_EN;
+	else
+		value &= ~AR803X_LPI_EN;
+	phy_write_mmd_indirect(phydev, 0x805D, MDIO_MMD_PCS,
+			       MDIO_DEVAD_NONE, value);
+}
+
 static int ar8021_config(struct phy_device *phydev)
 {
 	phy_write(phydev, MDIO_DEVAD_NONE, 0x00, 0x1200);
@@ -29,6 +47,11 @@ static int ar8021_config(struct phy_device *phydev)
 
 static int ar8031_config(struct phy_device *phydev)
 {
+#ifdef CONFIG_PHY_ATHEROS_SMART_EEE
+	ar803x_enable_smart_eee(phydev, true);
+#else
+	ar803x_enable_smart_eee(phydev, false);
+#endif
 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
 		phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
@@ -57,6 +80,11 @@ static int ar8035_config(struct phy_device *phydev)
 {
 	int regval;
 
+#ifdef CONFIG_PHY_ATHEROS_SMART_EEE
+	ar803x_enable_smart_eee(phydev, true);
+#else
+	ar803x_enable_smart_eee(phydev, false);
+#endif
 	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
 	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
 	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
-- 
2.7.4



More information about the U-Boot mailing list