aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/mv88e6xxx.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2015-04-01 22:06:37 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-01 22:55:41 -0400
commit2f40c6981ac0adcaa2b3fc64e6ae81f80809aec8 (patch)
tree24a434d77928f251de1cedc5cd0d4fa95671857b /drivers/net/dsa/mv88e6xxx.c
parentfd3a0ee4063e4f44d915df8f117d9e0d8b05950a (diff)
net: dsa: mv88e6xxx: Add missing mutex's in EEE operations.
The phy_mutex should be held while reading and writing to the phy. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx.c59
1 files changed, 30 insertions, 29 deletions
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 7c4c04bb0cb0..d9a78c71a4bb 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -701,53 +701,54 @@ static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
701 701
702int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) 702int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
703{ 703{
704 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
704 int reg; 705 int reg;
705 706
706 reg = mv88e6xxx_phy_read_indirect(ds, port, 16); 707 mutex_lock(&ps->phy_mutex);
708
709 reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
707 if (reg < 0) 710 if (reg < 0)
708 return -EOPNOTSUPP; 711 goto out;
709 712
710 e->eee_enabled = !!(reg & 0x0200); 713 e->eee_enabled = !!(reg & 0x0200);
711 e->tx_lpi_enabled = !!(reg & 0x0100); 714 e->tx_lpi_enabled = !!(reg & 0x0100);
712 715
713 reg = REG_READ(REG_PORT(port), 0); 716 reg = mv88e6xxx_reg_read(ds, REG_PORT(port), 0);
714 e->eee_active = !!(reg & 0x0040);
715
716 return 0;
717}
718
719static int mv88e6xxx_eee_enable_set(struct dsa_switch *ds, int port,
720 bool eee_enabled, bool tx_lpi_enabled)
721{
722 int reg, nreg;
723
724 reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
725 if (reg < 0) 717 if (reg < 0)
726 return reg; 718 goto out;
727
728 nreg = reg & ~0x0300;
729 if (eee_enabled)
730 nreg |= 0x0200;
731 if (tx_lpi_enabled)
732 nreg |= 0x0100;
733 719
734 if (nreg != reg) 720 e->eee_active = !!(reg & 0x0040);
735 return _mv88e6xxx_phy_write_indirect(ds, port, 16, nreg); 721 reg = 0;
736 722
737 return 0; 723out:
724 mutex_unlock(&ps->phy_mutex);
725 return reg;
738} 726}
739 727
740int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, 728int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
741 struct phy_device *phydev, struct ethtool_eee *e) 729 struct phy_device *phydev, struct ethtool_eee *e)
742{ 730{
731 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
732 int reg;
743 int ret; 733 int ret;
744 734
745 ret = mv88e6xxx_eee_enable_set(ds, port, e->eee_enabled, 735 mutex_lock(&ps->phy_mutex);
746 e->tx_lpi_enabled);
747 if (ret)
748 return -EOPNOTSUPP;
749 736
750 return 0; 737 ret = _mv88e6xxx_phy_read_indirect(ds, port, 16);
738 if (ret < 0)
739 goto out;
740
741 reg = ret & ~0x0300;
742 if (e->eee_enabled)
743 reg |= 0x0200;
744 if (e->tx_lpi_enabled)
745 reg |= 0x0100;
746
747 ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg);
748out:
749 mutex_unlock(&ps->phy_mutex);
750
751 return ret;
751} 752}
752 753
753static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) 754static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)