1 From 60df02b6ea4581d72eb7a3ab7204504a54059b72 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Fri, 14 May 2021 23:00:08 +0200
4 Subject: [PATCH] net: dsa: qca8k: dsa: qca8k: protect MASTER busy_wait with
7 MDIO_MASTER operation have a dedicated busy wait that is not protected
8 by the mdio mutex. This can cause situation where the MASTER operation
9 is done and a normal operation is executed between the MASTER read/write
10 and the MASTER busy_wait. Rework the qca8k_mdio_read/write function to
11 address this issue by binding the lock for the whole MASTER operation
12 and not only the mdio read/write common operation.
14 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
15 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
16 Signed-off-by: David S. Miller <davem@davemloft.net>
18 drivers/net/dsa/qca8k.c | 68 +++++++++++++++++++++++++++++++++--------
19 1 file changed, 55 insertions(+), 13 deletions(-)
21 --- a/drivers/net/dsa/qca8k.c
22 +++ b/drivers/net/dsa/qca8k.c
23 @@ -628,8 +628,31 @@ qca8k_port_to_phy(int port)
27 +qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
33 + qca8k_split_addr(reg, &r1, &r2, &page);
35 + ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0,
36 + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
37 + priv->bus, 0x10 | r2, r1);
39 + /* Check if qca8k_read has failed for a different reason
40 + * before returnting -ETIMEDOUT
42 + if (ret < 0 && val < 0)
49 qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
55 @@ -645,12 +668,21 @@ qca8k_mdio_write(struct qca8k_priv *priv
56 QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
57 QCA8K_MDIO_MASTER_DATA(data);
59 - ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
60 + qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
62 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
64 + ret = qca8k_set_page(priv->bus, page);
69 + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
71 - ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
72 - QCA8K_MDIO_MASTER_BUSY);
73 + ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
74 + QCA8K_MDIO_MASTER_BUSY);
77 + mutex_unlock(&priv->bus->mdio_lock);
79 /* even if the busy_wait timeouts try to clear the MASTER_EN */
80 qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
81 @@ -662,6 +694,7 @@ qca8k_mdio_write(struct qca8k_priv *priv
83 qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
89 @@ -676,21 +709,30 @@ qca8k_mdio_read(struct qca8k_priv *priv,
90 QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
91 QCA8K_MDIO_MASTER_REG_ADDR(regnum);
93 - ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
96 + qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
98 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
100 - ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
101 - QCA8K_MDIO_MASTER_BUSY);
102 + ret = qca8k_set_page(priv->bus, page);
107 - val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL);
110 + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
112 + ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
113 + QCA8K_MDIO_MASTER_BUSY);
117 + val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
118 val &= QCA8K_MDIO_MASTER_DATA_MASK;
121 + mutex_unlock(&priv->bus->mdio_lock);
124 + val &= QCA8K_MDIO_MASTER_DATA_MASK;
126 /* even if the busy_wait timeouts try to clear the MASTER_EN */
127 qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
128 QCA8K_MDIO_MASTER_EN);