ramips: mt7530 swconfig: fix race condition in register access
[openwrt/staging/jow.git] / target / linux / ramips / files / drivers / net / ethernet / ralink / mt7530.c
index 367b8d9ac4569f00972e89f3a48e45b09718293b..b4632d39904fcb682eac2e4429ec574171658ac7 100644 (file)
 
 #define MT7530_CPU_PORT                6
 #define MT7530_NUM_PORTS       8
-#ifdef CONFIG_SOC_MT7621
-#define MT7530_NUM_VLANS       4095
-#else
 #define MT7530_NUM_VLANS       16
-#endif
 #define MT7530_MAX_VID         4095
 #define MT7530_MIN_VID         0
 #define MT7530_NUM_ARL_RECORDS 2048
@@ -50,9 +46,6 @@
 #define MT7530_PORT_MIB_TXB_ID 2       /* TxGOC */
 #define MT7530_PORT_MIB_RXB_ID 6       /* RxGOC */
 
-#define MT7621_PORT_MIB_TXB_ID 18      /* TxByte */
-#define MT7621_PORT_MIB_RXB_ID 37      /* RxByte */
-
 /* registers */
 #define REG_ESW_WT_MAC_MFC             0x10
 
@@ -159,50 +152,6 @@ static const struct mt7xxx_mib_desc mt7620_port_mibs[] = {
        MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC2N, "RxEPC2")
 };
 
-static const struct mt7xxx_mib_desc mt7621_mibs[] = {
-       MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"),
-       MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"),
-       MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"),
-       MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"),
-       MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"),
-       MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"),
-       MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"),
-       MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"),
-       MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"),
-       MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"),
-       MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"),
-       MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"),
-       MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"),
-       MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"),
-       MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"),
-       MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"),
-       MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"),
-       MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"),
-       MIB_DESC(2, MT7621_STATS_TOC, "TxByte"),
-       MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"),
-       MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"),
-       MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"),
-       MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"),
-       MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"),
-       MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"),
-       MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"),
-       MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"),
-       MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"),
-       MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"),
-       MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"),
-       MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"),
-       MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"),
-       MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"),
-       MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"),
-       MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"),
-       MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"),
-       MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"),
-       MIB_DESC(2, MT7621_STATS_ROC, "RxByte"),
-       MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"),
-       MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"),
-       MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop")
-};
-
 enum {
        /* Global attributes. */
        MT7530_ATTR_ENABLE_VLAN,
@@ -341,9 +290,11 @@ mt7530_r32(struct mt7530_priv *priv, u32 reg)
        if (priv->bus) {
                u16 high, low;
 
-               mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
-               low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf);
-               high = mdiobus_read(priv->bus, 0x1f, 0x10);
+               mutex_lock(&priv->bus->mdio_lock);
+               __mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+               low = __mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf);
+               high = __mdiobus_read(priv->bus, 0x1f, 0x10);
+               mutex_unlock(&priv->bus->mdio_lock);
 
                return (high << 16) | (low & 0xffff);
        }
@@ -358,9 +309,11 @@ static void
 mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val)
 {
        if (priv->bus) {
-               mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
-               mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf,  val & 0xffff);
-               mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16);
+               mutex_lock(&priv->bus->mdio_lock);
+               __mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+               __mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf,  val & 0xffff);
+               __mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16);
+               mutex_unlock(&priv->bus->mdio_lock);
                return;
        }
 
@@ -510,14 +463,6 @@ mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
        return 0;
 }
 
-static int
-mt7621_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
-               struct switch_val *val)
-{
-       val->value.i = val->port_vlan;
-       return 0;
-}
-
 static int
 mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
                struct switch_val *val)
@@ -610,7 +555,6 @@ mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid,
        int port;
        u32 val;
 
-#ifndef CONFIG_SOC_MT7621
        /* vid of vlan */
        val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan));
        if (vlan % 2 == 0) {
@@ -621,7 +565,6 @@ mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid,
                val |= (vid << 12);
        }
        mt7530_w32(priv, REG_ESW_VLAN_VTIM(vlan), val);
-#endif
 
        /* vlan port membership */
        if (ports)
@@ -642,11 +585,7 @@ mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid,
        mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val);
 
        /* write to vlan table */
-#ifdef CONFIG_SOC_MT7621
-       mt7530_vtcr(priv, 1, vid);
-#else
        mt7530_vtcr(priv, 1, vlan);
-#endif
 }
 
 static int
@@ -799,53 +738,6 @@ mt7530_get_port_link(struct switch_dev *dev,  int port,
        return 0;
 }
 
-static u64 get_mib_counter(struct mt7530_priv *priv, int i, int port)
-{
-       unsigned int port_base;
-       u64 lo;
-
-       port_base = MT7621_MIB_COUNTER_BASE +
-                   MT7621_MIB_COUNTER_PORT_OFFSET * port;
-
-       lo = mt7530_r32(priv, port_base + mt7621_mibs[i].offset);
-       if (mt7621_mibs[i].size == 2) {
-               u64 hi;
-
-               hi = mt7530_r32(priv, port_base + mt7621_mibs[i].offset + 4);
-               lo |= hi << 32;
-       }
-
-       return lo;
-}
-
-static int mt7621_sw_get_port_mib(struct switch_dev *dev,
-                                 const struct switch_attr *attr,
-                                 struct switch_val *val)
-{
-       static char buf[4096];
-       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
-       int i, len = 0;
-
-       if (val->port_vlan >= MT7530_NUM_PORTS)
-               return -EINVAL;
-
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "Port %d MIB counters\n", val->port_vlan);
-
-       for (i = 0; i < ARRAY_SIZE(mt7621_mibs); ++i) {
-               u64 counter;
-               len += snprintf(buf + len, sizeof(buf) - len,
-                               "%-11s: ", mt7621_mibs[i].name);
-               counter = get_mib_counter(priv, i, val->port_vlan);
-               len += snprintf(buf + len, sizeof(buf) - len, "%llu\n",
-                               counter);
-       }
-
-       val->value.s = buf;
-       val->len = len;
-       return 0;
-}
-
 static u64 get_mib_counter_7620(struct mt7530_priv *priv, int i)
 {
        return mt7530_r32(priv, MT7620_MIB_COUNTER_BASE + mt7620_mibs[i].offset);
@@ -1019,20 +911,6 @@ static int mt7530_get_port_stats(struct switch_dev *dev, int port,
        return 0;
 }
 
-static int mt7621_get_port_stats(struct switch_dev *dev, int port,
-                                       struct switch_port_stats *stats)
-{
-       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
-
-       if (port < 0 || port >= MT7530_NUM_PORTS)
-               return -EINVAL;
-
-       stats->tx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_TXB_ID, port);
-       stats->rx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_RXB_ID, port);
-
-       return 0;
-}
-
 static const struct switch_attr mt7530_global[] = {
        {
                .type = SWITCH_TYPE_INT,
@@ -1065,41 +943,6 @@ static const struct switch_attr mt7530_global[] = {
        },
 };
 
-static const struct switch_attr mt7621_port[] = {
-       {
-               .type = SWITCH_TYPE_STRING,
-               .name = "mib",
-               .description = "Get MIB counters for port",
-               .get = mt7621_sw_get_port_mib,
-               .set = NULL,
-       }, {
-               .type = SWITCH_TYPE_INT,
-               .name = "enable_mirror_rx",
-               .description = "Enable mirroring of RX packets",
-               .set = mt7530_set_port_mirror_rx,
-               .get = mt7530_get_port_mirror_rx,
-               .max = 1,
-       }, {
-               .type = SWITCH_TYPE_INT,
-               .name = "enable_mirror_tx",
-               .description = "Enable mirroring of TX packets",
-               .set = mt7530_set_port_mirror_tx,
-               .get = mt7530_get_port_mirror_tx,
-               .max = 1,
-       },
-};
-
-static const struct switch_attr mt7621_vlan[] = {
-       {
-               .type = SWITCH_TYPE_INT,
-               .name = "vid",
-               .description = "VLAN ID (0-4094)",
-               .set = mt7530_set_vid,
-               .get = mt7621_get_vid,
-               .max = 4094,
-       },
-};
-
 static const struct switch_attr mt7530_port[] = {
        {
                .type = SWITCH_TYPE_STRING,
@@ -1135,29 +978,6 @@ static const struct switch_attr mt7530_vlan[] = {
        },
 };
 
-static const struct switch_dev_ops mt7621_ops = {
-       .attr_global = {
-               .attr = mt7530_global,
-               .n_attr = ARRAY_SIZE(mt7530_global),
-       },
-       .attr_port = {
-               .attr = mt7621_port,
-               .n_attr = ARRAY_SIZE(mt7621_port),
-       },
-       .attr_vlan = {
-               .attr = mt7621_vlan,
-               .n_attr = ARRAY_SIZE(mt7621_vlan),
-       },
-       .get_vlan_ports = mt7530_get_vlan_ports,
-       .set_vlan_ports = mt7530_set_vlan_ports,
-       .get_port_pvid = mt7530_get_port_pvid,
-       .set_port_pvid = mt7530_set_port_pvid,
-       .get_port_link = mt7530_get_port_link,
-       .get_port_stats = mt7621_get_port_stats,
-       .apply_config = mt7530_apply_config,
-       .reset_switch = mt7530_reset_switch,
-};
-
 static const struct switch_dev_ops mt7530_ops = {
        .attr_global = {
                .attr = mt7530_global,
@@ -1201,9 +1021,6 @@ mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vl
        if (bus) {
                swdev->alias = "mt7530";
                swdev->name = "mt7530";
-       } else if (IS_ENABLED(CONFIG_SOC_MT7621)) {
-               swdev->alias = "mt7621";
-               swdev->name = "mt7621";
        } else {
                swdev->alias = "mt7620";
                swdev->name = "mt7620";
@@ -1211,10 +1028,7 @@ mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vl
        swdev->cpu_port = MT7530_CPU_PORT;
        swdev->ports = MT7530_NUM_PORTS;
        swdev->vlans = MT7530_NUM_VLANS;
-       if (IS_ENABLED(CONFIG_SOC_MT7621))
-               swdev->ops = &mt7621_ops;
-       else
-               swdev->ops = &mt7530_ops;
+       swdev->ops = &mt7530_ops;
 
        ret = register_switch(swdev, NULL);
        if (ret) {
@@ -1229,7 +1043,7 @@ mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vl
        mt7530_apply_config(swdev);
 
        /* magic vodoo */
-       if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) !=  0x1117edf) {
+       if (bus && mt7530_r32(mt7530, REG_HWTRAP) !=  0x1117edf) {
                dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n");
                mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf);
        }