summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2015-05-05 19:09:53 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-09 16:05:53 -0400
commit3898c148589752687524ff552a498a8fb4c80667 (patch)
tree296718b00127e33e5e5c71c2b6523f63c998ffa5 /drivers/net/dsa
parent1441f4e59695682909bbbb7d5740c3fff326a4c3 (diff)
net: dsa: mv88e6xxx: Replace PHY mutex by SMI mutex
The SMI bus is the bottleneck in all switch operations, not the granularity of locks. Replace the PHY mutex by the SMI mutex to make the locking concept simpler. The REG_READ/REG_WRITE macros cannot be used while holding the SMI mutex, since they try to acquire it. Replace with calls to the appropriate function which does not try to get the mutex. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r--drivers/net/dsa/mv88e6xxx.c121
-rw-r--r--drivers/net/dsa/mv88e6xxx.h1
2 files changed, 63 insertions, 59 deletions
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index f38d8dfa934a..e974d26c1a03 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -199,20 +199,20 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
199 return 0; 199 return 0;
200} 200}
201 201
202/* Must be called with phy mutex held */ 202/* Must be called with SMI mutex held */
203static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) 203static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
204{ 204{
205 if (addr >= 0) 205 if (addr >= 0)
206 return mv88e6xxx_reg_read(ds, addr, regnum); 206 return _mv88e6xxx_reg_read(ds, addr, regnum);
207 return 0xffff; 207 return 0xffff;
208} 208}
209 209
210/* Must be called with phy mutex held */ 210/* Must be called with SMI mutex held */
211static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, 211static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum,
212 u16 val) 212 u16 val)
213{ 213{
214 if (addr >= 0) 214 if (addr >= 0)
215 return mv88e6xxx_reg_write(ds, addr, regnum, val); 215 return _mv88e6xxx_reg_write(ds, addr, regnum, val);
216 return 0; 216 return 0;
217} 217}
218 218
@@ -762,7 +762,7 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
762 762
763 *temp = 0; 763 *temp = 0;
764 764
765 mutex_lock(&ps->phy_mutex); 765 mutex_lock(&ps->smi_mutex);
766 766
767 ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6); 767 ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6);
768 if (ret < 0) 768 if (ret < 0)
@@ -795,19 +795,23 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
795 795
796error: 796error:
797 _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0); 797 _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0);
798 mutex_unlock(&ps->phy_mutex); 798 mutex_unlock(&ps->smi_mutex);
799 return ret; 799 return ret;
800} 800}
801#endif /* CONFIG_NET_DSA_HWMON */ 801#endif /* CONFIG_NET_DSA_HWMON */
802 802
803static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask) 803/* Must be called with SMI lock held */
804static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
805 u16 mask)
804{ 806{
805 unsigned long timeout = jiffies + HZ / 10; 807 unsigned long timeout = jiffies + HZ / 10;
806 808
807 while (time_before(jiffies, timeout)) { 809 while (time_before(jiffies, timeout)) {
808 int ret; 810 int ret;
809 811
810 ret = REG_READ(reg, offset); 812 ret = _mv88e6xxx_reg_read(ds, reg, offset);
813 if (ret < 0)
814 return ret;
811 if (!(ret & mask)) 815 if (!(ret & mask))
812 return 0; 816 return 0;
813 817
@@ -816,10 +820,22 @@ static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
816 return -ETIMEDOUT; 820 return -ETIMEDOUT;
817} 821}
818 822
819int mv88e6xxx_phy_wait(struct dsa_switch *ds) 823static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
824{
825 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
826 int ret;
827
828 mutex_lock(&ps->smi_mutex);
829 ret = _mv88e6xxx_wait(ds, reg, offset, mask);
830 mutex_unlock(&ps->smi_mutex);
831
832 return ret;
833}
834
835static int _mv88e6xxx_phy_wait(struct dsa_switch *ds)
820{ 836{
821 return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP, 837 return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
822 GLOBAL2_SMI_OP_BUSY); 838 GLOBAL2_SMI_OP_BUSY);
823} 839}
824 840
825int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds) 841int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
@@ -835,56 +851,46 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
835} 851}
836 852
837/* Must be called with SMI lock held */ 853/* Must be called with SMI lock held */
838static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
839{
840 unsigned long timeout = jiffies + HZ / 10;
841
842 while (time_before(jiffies, timeout)) {
843 int ret;
844
845 ret = _mv88e6xxx_reg_read(ds, reg, offset);
846 if (ret < 0)
847 return ret;
848 if (!(ret & mask))
849 return 0;
850
851 usleep_range(1000, 2000);
852 }
853 return -ETIMEDOUT;
854}
855
856/* Must be called with SMI lock held */
857static int _mv88e6xxx_atu_wait(struct dsa_switch *ds) 854static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
858{ 855{
859 return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP, 856 return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP,
860 GLOBAL_ATU_OP_BUSY); 857 GLOBAL_ATU_OP_BUSY);
861} 858}
862 859
863/* Must be called with phy mutex held */ 860/* Must be called with SMI mutex held */
864static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, 861static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
865 int regnum) 862 int regnum)
866{ 863{
867 int ret; 864 int ret;
868 865
869 REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_OP, 866 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
870 GLOBAL2_SMI_OP_22_READ | (addr << 5) | regnum); 867 GLOBAL2_SMI_OP_22_READ | (addr << 5) |
868 regnum);
869 if (ret < 0)
870 return ret;
871 871
872 ret = mv88e6xxx_phy_wait(ds); 872 ret = _mv88e6xxx_phy_wait(ds);
873 if (ret < 0) 873 if (ret < 0)
874 return ret; 874 return ret;
875 875
876 return REG_READ(REG_GLOBAL2, GLOBAL2_SMI_DATA); 876 return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA);
877} 877}
878 878
879/* Must be called with phy mutex held */ 879/* Must be called with SMI mutex held */
880static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, 880static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
881 int regnum, u16 val) 881 int regnum, u16 val)
882{ 882{
883 REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_DATA, val); 883 int ret;
884 REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_OP, 884
885 GLOBAL2_SMI_OP_22_WRITE | (addr << 5) | regnum); 885 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
886 if (ret < 0)
887 return ret;
886 888
887 return mv88e6xxx_phy_wait(ds); 889 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
890 GLOBAL2_SMI_OP_22_WRITE | (addr << 5) |
891 regnum);
892
893 return _mv88e6xxx_phy_wait(ds);
888} 894}
889 895
890int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) 896int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
@@ -892,7 +898,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
892 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 898 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
893 int reg; 899 int reg;
894 900
895 mutex_lock(&ps->phy_mutex); 901 mutex_lock(&ps->smi_mutex);
896 902
897 reg = _mv88e6xxx_phy_read_indirect(ds, port, 16); 903 reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
898 if (reg < 0) 904 if (reg < 0)
@@ -901,7 +907,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
901 e->eee_enabled = !!(reg & 0x0200); 907 e->eee_enabled = !!(reg & 0x0200);
902 e->tx_lpi_enabled = !!(reg & 0x0100); 908 e->tx_lpi_enabled = !!(reg & 0x0100);
903 909
904 reg = mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS); 910 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS);
905 if (reg < 0) 911 if (reg < 0)
906 goto out; 912 goto out;
907 913
@@ -909,7 +915,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
909 reg = 0; 915 reg = 0;
910 916
911out: 917out:
912 mutex_unlock(&ps->phy_mutex); 918 mutex_unlock(&ps->smi_mutex);
913 return reg; 919 return reg;
914} 920}
915 921
@@ -920,7 +926,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
920 int reg; 926 int reg;
921 int ret; 927 int ret;
922 928
923 mutex_lock(&ps->phy_mutex); 929 mutex_lock(&ps->smi_mutex);
924 930
925 ret = _mv88e6xxx_phy_read_indirect(ds, port, 16); 931 ret = _mv88e6xxx_phy_read_indirect(ds, port, 16);
926 if (ret < 0) 932 if (ret < 0)
@@ -934,7 +940,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
934 940
935 ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg); 941 ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg);
936out: 942out:
937 mutex_unlock(&ps->phy_mutex); 943 mutex_unlock(&ps->smi_mutex);
938 944
939 return ret; 945 return ret;
940} 946}
@@ -1568,7 +1574,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
1568 1574
1569 mutex_init(&ps->smi_mutex); 1575 mutex_init(&ps->smi_mutex);
1570 mutex_init(&ps->stats_mutex); 1576 mutex_init(&ps->stats_mutex);
1571 mutex_init(&ps->phy_mutex);
1572 1577
1573 ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; 1578 ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
1574 1579
@@ -1722,14 +1727,14 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
1722 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 1727 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1723 int ret; 1728 int ret;
1724 1729
1725 mutex_lock(&ps->phy_mutex); 1730 mutex_lock(&ps->smi_mutex);
1726 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); 1731 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
1727 if (ret < 0) 1732 if (ret < 0)
1728 goto error; 1733 goto error;
1729 ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); 1734 ret = _mv88e6xxx_phy_read_indirect(ds, port, reg);
1730error: 1735error:
1731 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); 1736 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
1732 mutex_unlock(&ps->phy_mutex); 1737 mutex_unlock(&ps->smi_mutex);
1733 return ret; 1738 return ret;
1734} 1739}
1735 1740
@@ -1739,7 +1744,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
1739 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 1744 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1740 int ret; 1745 int ret;
1741 1746
1742 mutex_lock(&ps->phy_mutex); 1747 mutex_lock(&ps->smi_mutex);
1743 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); 1748 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
1744 if (ret < 0) 1749 if (ret < 0)
1745 goto error; 1750 goto error;
@@ -1747,7 +1752,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
1747 ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); 1752 ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val);
1748error: 1753error:
1749 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); 1754 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
1750 mutex_unlock(&ps->phy_mutex); 1755 mutex_unlock(&ps->smi_mutex);
1751 return ret; 1756 return ret;
1752} 1757}
1753 1758
@@ -1770,9 +1775,9 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
1770 if (addr < 0) 1775 if (addr < 0)
1771 return addr; 1776 return addr;
1772 1777
1773 mutex_lock(&ps->phy_mutex); 1778 mutex_lock(&ps->smi_mutex);
1774 ret = _mv88e6xxx_phy_read(ds, addr, regnum); 1779 ret = _mv88e6xxx_phy_read(ds, addr, regnum);
1775 mutex_unlock(&ps->phy_mutex); 1780 mutex_unlock(&ps->smi_mutex);
1776 return ret; 1781 return ret;
1777} 1782}
1778 1783
@@ -1786,9 +1791,9 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
1786 if (addr < 0) 1791 if (addr < 0)
1787 return addr; 1792 return addr;
1788 1793
1789 mutex_lock(&ps->phy_mutex); 1794 mutex_lock(&ps->smi_mutex);
1790 ret = _mv88e6xxx_phy_write(ds, addr, regnum, val); 1795 ret = _mv88e6xxx_phy_write(ds, addr, regnum, val);
1791 mutex_unlock(&ps->phy_mutex); 1796 mutex_unlock(&ps->smi_mutex);
1792 return ret; 1797 return ret;
1793} 1798}
1794 1799
@@ -1802,9 +1807,9 @@ mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
1802 if (addr < 0) 1807 if (addr < 0)
1803 return addr; 1808 return addr;
1804 1809
1805 mutex_lock(&ps->phy_mutex); 1810 mutex_lock(&ps->smi_mutex);
1806 ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum); 1811 ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum);
1807 mutex_unlock(&ps->phy_mutex); 1812 mutex_unlock(&ps->smi_mutex);
1808 return ret; 1813 return ret;
1809} 1814}
1810 1815
@@ -1819,9 +1824,9 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
1819 if (addr < 0) 1824 if (addr < 0)
1820 return addr; 1825 return addr;
1821 1826
1822 mutex_lock(&ps->phy_mutex); 1827 mutex_lock(&ps->smi_mutex);
1823 ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val); 1828 ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
1824 mutex_unlock(&ps->phy_mutex); 1829 mutex_unlock(&ps->smi_mutex);
1825 return ret; 1830 return ret;
1826} 1831}
1827 1832
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index aafcb1a0a616..e10ccdb4ffbc 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -377,7 +377,6 @@ int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
377void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, 377void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
378 struct ethtool_regs *regs, void *_p); 378 struct ethtool_regs *regs, void *_p);
379int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); 379int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
380int mv88e6xxx_phy_wait(struct dsa_switch *ds);
381int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds); 380int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
382int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds); 381int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
383int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum); 382int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);