From: Greg Kroah-Hartman Date: Wed, 13 Oct 2021 09:12:23 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.289~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ab29672532a67a60df3c40380cce90f12e67865;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: net-phy-bcm7xxx-fixed-indirect-mmd-operations.patch --- diff --git a/queue-4.14/net-phy-bcm7xxx-fixed-indirect-mmd-operations.patch b/queue-4.14/net-phy-bcm7xxx-fixed-indirect-mmd-operations.patch new file mode 100644 index 00000000000..fd1816016cd --- /dev/null +++ b/queue-4.14/net-phy-bcm7xxx-fixed-indirect-mmd-operations.patch @@ -0,0 +1,148 @@ +From d88fd1b546ff19c8040cfaea76bf16aed1c5a0bb Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 28 Sep 2021 13:32:33 -0700 +Subject: net: phy: bcm7xxx: Fixed indirect MMD operations + +From: Florian Fainelli + +commit d88fd1b546ff19c8040cfaea76bf16aed1c5a0bb upstream. + +When EEE support was added to the 28nm EPHY it was assumed that it would +be able to support the standard clause 45 over clause 22 register access +method. It turns out that the PHY does not support that, which is the +very reason for using the indirect shadow mode 2 bank 3 access method. + +Implement {read,write}_mmd to allow the standard PHY library routines +pertaining to EEE querying and configuration to work correctly on these +PHYs. This forces us to implement a __phy_set_clr_bits() function that +does not grab the MDIO bus lock since the PHY driver's {read,write}_mmd +functions are always called with that lock held. + +Fixes: 83ee102a6998 ("net: phy: bcm7xxx: add support for 28nm EPHY") +[florian: adjust locking since phy_{read,write}_mmd are called with no +PHYLIB locks held] +Signed-off-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/bcm7xxx.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 94 insertions(+) + +--- a/drivers/net/phy/bcm7xxx.c ++++ b/drivers/net/phy/bcm7xxx.c +@@ -30,7 +30,12 @@ + #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe + #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf + #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a ++#define MII_BCM7XXX_SHD_3_PCS_CTRL 0x0 ++#define MII_BCM7XXX_SHD_3_PCS_STATUS 0x1 ++#define MII_BCM7XXX_SHD_3_EEE_CAP 0x2 + #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3 ++#define MII_BCM7XXX_SHD_3_EEE_LP 0x4 ++#define MII_BCM7XXX_SHD_3_EEE_WK_ERR 0x5 + #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6 + #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400 + #define MII_BCM7XXX_SHD_3_AN_STAT 0xb +@@ -462,6 +467,93 @@ static int bcm7xxx_28nm_ephy_config_init + return bcm7xxx_28nm_ephy_apd_enable(phydev); + } + ++#define MII_BCM7XXX_REG_INVALID 0xff ++ ++static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum) ++{ ++ switch (regnum) { ++ case MDIO_CTRL1: ++ return MII_BCM7XXX_SHD_3_PCS_CTRL; ++ case MDIO_STAT1: ++ return MII_BCM7XXX_SHD_3_PCS_STATUS; ++ case MDIO_PCS_EEE_ABLE: ++ return MII_BCM7XXX_SHD_3_EEE_CAP; ++ case MDIO_AN_EEE_ADV: ++ return MII_BCM7XXX_SHD_3_AN_EEE_ADV; ++ case MDIO_AN_EEE_LPABLE: ++ return MII_BCM7XXX_SHD_3_EEE_LP; ++ case MDIO_PCS_EEE_WK_ERR: ++ return MII_BCM7XXX_SHD_3_EEE_WK_ERR; ++ default: ++ return MII_BCM7XXX_REG_INVALID; ++ } ++} ++ ++static bool bcm7xxx_28nm_ephy_dev_valid(int devnum) ++{ ++ return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS; ++} ++ ++static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev, ++ int devnum, u16 regnum) ++{ ++ u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); ++ int ret; ++ ++ if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || ++ shd == MII_BCM7XXX_REG_INVALID) ++ return -EOPNOTSUPP; ++ ++ /* set shadow mode 2 */ ++ ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, ++ MII_BCM7XXX_SHD_MODE_2, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* Access the desired shadow register address */ ++ ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); ++ if (ret < 0) ++ goto reset_shadow_mode; ++ ++ ret = phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT); ++ ++reset_shadow_mode: ++ /* reset shadow mode 2 */ ++ phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, ++ MII_BCM7XXX_SHD_MODE_2); ++ return ret; ++} ++ ++static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev, ++ int devnum, u16 regnum, u16 val) ++{ ++ u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); ++ int ret; ++ ++ if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || ++ shd == MII_BCM7XXX_REG_INVALID) ++ return -EOPNOTSUPP; ++ ++ /* set shadow mode 2 */ ++ ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, ++ MII_BCM7XXX_SHD_MODE_2, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* Access the desired shadow register address */ ++ ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); ++ if (ret < 0) ++ goto reset_shadow_mode; ++ ++ /* Write the desired value in the shadow register */ ++ phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val); ++ ++reset_shadow_mode: ++ /* reset shadow mode 2 */ ++ return phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, ++ MII_BCM7XXX_SHD_MODE_2); ++} ++ + static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev) + { + int ret; +@@ -637,6 +729,8 @@ static int bcm7xxx_28nm_probe(struct phy + .get_strings = bcm_phy_get_strings, \ + .get_stats = bcm7xxx_28nm_get_phy_stats, \ + .probe = bcm7xxx_28nm_probe, \ ++ .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \ ++ .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \ + } + + #define BCM7XXX_40NM_EPHY(_oui, _name) \ diff --git a/queue-4.14/series b/queue-4.14/series index adb73df3797..0592d0a727a 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -21,3 +21,4 @@ drm-nouveau-debugfs-fix-file-release-memory-leak.patch rtnetlink-fix-if_nlmsg_stats_size-under-estimation.patch i40e-fix-endless-loop-under-rtnl.patch i2c-acpi-fix-resource-leak-in-reconfiguration-device.patch +net-phy-bcm7xxx-fixed-indirect-mmd-operations.patch