Skip to content

Commit

Permalink
net: dsa: qca8k: cache lo and hi for mdio write
Browse files Browse the repository at this point in the history
From Documentation, we can cache lo and hi the same way we do with the
page. This massively reduce the mdio write as 3/4 of the time as we only
require to write the lo or hi part for a mdio write.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ansuel Smith authored and David S. Miller committed Feb 2, 2022
1 parent 4264350 commit 2481d20
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
61 changes: 49 additions & 12 deletions drivers/net/dsa/qca8k.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,44 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
*page = regaddr & 0x3ff;
}

static int
qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo)
{
u16 *cached_lo = &priv->mdio_cache.lo;
struct mii_bus *bus = priv->bus;
int ret;

if (lo == *cached_lo)
return 0;

ret = bus->write(bus, phy_id, regnum, lo);
if (ret < 0)
dev_err_ratelimited(&bus->dev,
"failed to write qca8k 32bit lo register\n");

*cached_lo = lo;
return 0;
}

static int
qca8k_set_hi(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 hi)
{
u16 *cached_hi = &priv->mdio_cache.hi;
struct mii_bus *bus = priv->bus;
int ret;

if (hi == *cached_hi)
return 0;

ret = bus->write(bus, phy_id, regnum, hi);
if (ret < 0)
dev_err_ratelimited(&bus->dev,
"failed to write qca8k 32bit hi register\n");

*cached_hi = hi;
return 0;
}

static int
qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val)
{
Expand All @@ -111,20 +149,17 @@ qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val)
}

static void
qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val)
qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val)
{
u16 lo, hi;
int ret;

lo = val & 0xffff;
hi = (u16)(val >> 16);

ret = bus->write(bus, phy_id, regnum, lo);
ret = qca8k_set_lo(priv, phy_id, regnum, lo);
if (ret >= 0)
ret = bus->write(bus, phy_id, regnum + 1, hi);
if (ret < 0)
dev_err_ratelimited(&bus->dev,
"failed to write qca8k 32bit register\n");
ret = qca8k_set_hi(priv, phy_id, regnum + 1, hi);
}

static int
Expand Down Expand Up @@ -400,7 +435,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
if (ret < 0)
goto exit;

qca8k_mii_write32(bus, 0x10 | r2, r1, val);
qca8k_mii_write32(priv, 0x10 | r2, r1, val);

exit:
mutex_unlock(&bus->mdio_lock);
Expand Down Expand Up @@ -433,7 +468,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_

val &= ~mask;
val |= write_val;
qca8k_mii_write32(bus, 0x10 | r2, r1, val);
qca8k_mii_write32(priv, 0x10 | r2, r1, val);

exit:
mutex_unlock(&bus->mdio_lock);
Expand Down Expand Up @@ -1117,14 +1152,14 @@ qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data)
if (ret)
goto exit;

qca8k_mii_write32(bus, 0x10 | r2, r1, val);
qca8k_mii_write32(priv, 0x10 | r2, r1, val);

ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
QCA8K_MDIO_MASTER_BUSY);

exit:
/* even if the busy_wait timeouts try to clear the MASTER_EN */
qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
qca8k_mii_write32(priv, 0x10 | r2, r1, 0);

mutex_unlock(&bus->mdio_lock);

Expand Down Expand Up @@ -1154,7 +1189,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum)
if (ret)
goto exit;

qca8k_mii_write32(bus, 0x10 | r2, r1, val);
qca8k_mii_write32(priv, 0x10 | r2, r1, val);

ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
QCA8K_MDIO_MASTER_BUSY);
Expand All @@ -1165,7 +1200,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum)

exit:
/* even if the busy_wait timeouts try to clear the MASTER_EN */
qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
qca8k_mii_write32(priv, 0x10 | r2, r1, 0);

mutex_unlock(&bus->mdio_lock);

Expand Down Expand Up @@ -3039,6 +3074,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
}

priv->mdio_cache.page = 0xffff;
priv->mdio_cache.lo = 0xffff;
priv->mdio_cache.hi = 0xffff;

/* Check the detected switch id */
ret = qca8k_read_switch_id(priv);
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/dsa/qca8k.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ struct qca8k_mdio_cache {
* mdio writes
*/
u16 page;
/* lo and hi can also be cached and from Documentation we can skip one
* extra mdio write if lo or hi is didn't change.
*/
u16 lo;
u16 hi;
};

struct qca8k_priv {
Expand Down

0 comments on commit 2481d20

Please sign in to comment.