summaryrefslogtreecommitdiff
path: root/drivers/net/phy/bcm-phy-lib.c
diff options
context:
space:
mode:
authorMichael Walle <michael@walle.cc>2020-05-13 19:35:21 +0300
committerDavid S. Miller <davem@davemloft.net>2020-05-13 22:52:38 +0300
commit7d7e7bce768b9e21eb1b741a901c19c2bef1cccc (patch)
treeef950302dcf999699e9814aef661dd771b648df3 /drivers/net/phy/bcm-phy-lib.c
parentea13d71887bd589d2f08ca74a3e1961dd68b678d (diff)
downloadlinux-7d7e7bce768b9e21eb1b741a901c19c2bef1cccc.tar.xz
net: phy: broadcom: add exp register access methods without buslock
Add helper to read and write expansion registers without taking the mdio lock. Please note, that this changes the semantics of the read and write. Before there was no lock between selecting the expansion register and the actual read/write. This may lead to access failures if there are parallel accesses. Instead take the bus lock during the whole access cycle. Signed-off-by: Michael Walle <michael@walle.cc> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/bcm-phy-lib.c')
-rw-r--r--drivers/net/phy/bcm-phy-lib.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index d5f9a2701989..a390812714ed 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -14,33 +14,57 @@
#define MII_BCM_CHANNEL_WIDTH 0x2000
#define BCM_CL45VEN_EEE_ADV 0x3c
-int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
+int __bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
{
int rc;
- rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+ rc = __phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
if (rc < 0)
return rc;
- return phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
+ return __phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
+}
+EXPORT_SYMBOL_GPL(__bcm_phy_write_exp);
+
+int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
+{
+ int rc;
+
+ phy_lock_mdio_bus(phydev);
+ rc = __bcm_phy_write_exp(phydev, reg, val);
+ phy_unlock_mdio_bus(phydev);
+
+ return rc;
}
EXPORT_SYMBOL_GPL(bcm_phy_write_exp);
-int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
+int __bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
{
int val;
- val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+ val = __phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
if (val < 0)
return val;
- val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
+ val = __phy_read(phydev, MII_BCM54XX_EXP_DATA);
/* Restore default value. It's O.K. if this write fails. */
- phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
+ __phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
return val;
}
+EXPORT_SYMBOL_GPL(__bcm_phy_read_exp);
+
+int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
+{
+ int rc;
+
+ phy_lock_mdio_bus(phydev);
+ rc = __bcm_phy_read_exp(phydev, reg);
+ phy_unlock_mdio_bus(phydev);
+
+ return rc;
+}
EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)