lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200323162730.88236-1-mail@david-bauer.net>
Date:   Mon, 23 Mar 2020 17:27:30 +0100
From:   David Bauer <mail@...id-bauer.net>
To:     netdev@...r.kernel.org
Subject: [PATCH] net: phy: at803x: select correct page on initialization

The Atheros AR8031 and AR8033 expose different registers for SGMII/Fiber
as well as the copper side of the PHY depending on the BT_BX_REG_SEL bit
in the chip configure register.

The driver assumes the copper side is selected on probe, but this might
not be the case depending which page was last selected by the
bootloader.

Select the copper page when initializing the configuration to circumvent
this.

Signed-off-by: David Bauer <mail@...id-bauer.net>
---
 drivers/net/phy/at803x.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 481cf48c9b9e..c027ae820a6a 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -103,6 +103,9 @@
 #define AT803X_CLK_OUT_STRENGTH_HALF		1
 #define AT803X_CLK_OUT_STRENGTH_QUARTER		2
 
+#define AT803X_PAGE_COPPER		0
+#define AT803X_PAGE_FIBER		1
+
 #define ATH9331_PHY_ID 0x004dd041
 #define ATH8030_PHY_ID 0x004dd076
 #define ATH8031_PHY_ID 0x004dd074
@@ -160,6 +163,21 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
 	return phy_write(phydev, AT803X_DEBUG_DATA, val);
 }
 
+static int at803x_switch_page(struct phy_device *phydev, u8 page)
+{
+	int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
+
+	if (ccr < 0)
+		return ccr;
+
+	if (page == AT803X_PAGE_COPPER)
+		ccr = ccr | AT803X_BT_BX_REG_SEL;
+	else
+		ccr = ccr & ~AT803X_BT_BX_REG_SEL;
+
+	return phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr);
+}
+
 static int at803x_enable_rx_delay(struct phy_device *phydev)
 {
 	return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
@@ -534,6 +552,12 @@ static int at803x_config_init(struct phy_device *phydev)
 {
 	int ret;
 
+	if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) {
+		ret = at803x_switch_page(phydev, AT803X_PAGE_COPPER);
+		if (ret < 0)
+			return ret;
+	}
+
 	/* The RX and TX delay default is:
 	 *   after HW reset: RX delay enabled and TX delay disabled
 	 *   after SW reset: RX delay enabled, while TX delay retains the
@@ -641,7 +665,7 @@ static int at803x_aneg_done(struct phy_device *phydev)
 		return aneg_done;
 
 	/* switch to SGMII/fiber page */
-	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
+	at803x_switch_page(phydev, AT803X_PAGE_FIBER);
 
 	/* check if the SGMII link is OK. */
 	if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
@@ -649,7 +673,7 @@ static int at803x_aneg_done(struct phy_device *phydev)
 		aneg_done = 0;
 	}
 	/* switch back to copper page */
-	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
+	at803x_switch_page(phydev, AT803X_PAGE_COPPER);
 
 	return aneg_done;
 }
-- 
2.25.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ