766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. From 2481d206fae7884cd07014fd1318e63af35e99eb Mon Sep 17 00:00:00 2001
  2. From: Ansuel Smith <[email protected]>
  3. Date: Wed, 2 Feb 2022 01:03:33 +0100
  4. Subject: [PATCH 14/16] net: dsa: qca8k: cache lo and hi for mdio write
  5. From Documentation, we can cache lo and hi the same way we do with the
  6. page. This massively reduce the mdio write as 3/4 of the time as we only
  7. require to write the lo or hi part for a mdio write.
  8. Signed-off-by: Ansuel Smith <[email protected]>
  9. Reviewed-by: Florian Fainelli <[email protected]>
  10. Signed-off-by: David S. Miller <[email protected]>
  11. ---
  12. drivers/net/dsa/qca8k.c | 61 +++++++++++++++++++++++++++++++++--------
  13. drivers/net/dsa/qca8k.h | 5 ++++
  14. 2 files changed, 54 insertions(+), 12 deletions(-)
  15. --- a/drivers/net/dsa/qca8k.c
  16. +++ b/drivers/net/dsa/qca8k.c
  17. @@ -89,6 +89,44 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u
  18. }
  19. static int
  20. +qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo)
  21. +{
  22. + u16 *cached_lo = &priv->mdio_cache.lo;
  23. + struct mii_bus *bus = priv->bus;
  24. + int ret;
  25. +
  26. + if (lo == *cached_lo)
  27. + return 0;
  28. +
  29. + ret = bus->write(bus, phy_id, regnum, lo);
  30. + if (ret < 0)
  31. + dev_err_ratelimited(&bus->dev,
  32. + "failed to write qca8k 32bit lo register\n");
  33. +
  34. + *cached_lo = lo;
  35. + return 0;
  36. +}
  37. +
  38. +static int
  39. +qca8k_set_hi(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 hi)
  40. +{
  41. + u16 *cached_hi = &priv->mdio_cache.hi;
  42. + struct mii_bus *bus = priv->bus;
  43. + int ret;
  44. +
  45. + if (hi == *cached_hi)
  46. + return 0;
  47. +
  48. + ret = bus->write(bus, phy_id, regnum, hi);
  49. + if (ret < 0)
  50. + dev_err_ratelimited(&bus->dev,
  51. + "failed to write qca8k 32bit hi register\n");
  52. +
  53. + *cached_hi = hi;
  54. + return 0;
  55. +}
  56. +
  57. +static int
  58. qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val)
  59. {
  60. int ret;
  61. @@ -111,7 +149,7 @@ qca8k_mii_read32(struct mii_bus *bus, in
  62. }
  63. static void
  64. -qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val)
  65. +qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val)
  66. {
  67. u16 lo, hi;
  68. int ret;
  69. @@ -119,12 +157,9 @@ qca8k_mii_write32(struct mii_bus *bus, i
  70. lo = val & 0xffff;
  71. hi = (u16)(val >> 16);
  72. - ret = bus->write(bus, phy_id, regnum, lo);
  73. + ret = qca8k_set_lo(priv, phy_id, regnum, lo);
  74. if (ret >= 0)
  75. - ret = bus->write(bus, phy_id, regnum + 1, hi);
  76. - if (ret < 0)
  77. - dev_err_ratelimited(&bus->dev,
  78. - "failed to write qca8k 32bit register\n");
  79. + ret = qca8k_set_hi(priv, phy_id, regnum + 1, hi);
  80. }
  81. static int
  82. @@ -400,7 +435,7 @@ qca8k_regmap_write(void *ctx, uint32_t r
  83. if (ret < 0)
  84. goto exit;
  85. - qca8k_mii_write32(bus, 0x10 | r2, r1, val);
  86. + qca8k_mii_write32(priv, 0x10 | r2, r1, val);
  87. exit:
  88. mutex_unlock(&bus->mdio_lock);
  89. @@ -433,7 +468,7 @@ qca8k_regmap_update_bits(void *ctx, uint
  90. val &= ~mask;
  91. val |= write_val;
  92. - qca8k_mii_write32(bus, 0x10 | r2, r1, val);
  93. + qca8k_mii_write32(priv, 0x10 | r2, r1, val);
  94. exit:
  95. mutex_unlock(&bus->mdio_lock);
  96. @@ -1117,14 +1152,14 @@ qca8k_mdio_write(struct qca8k_priv *priv
  97. if (ret)
  98. goto exit;
  99. - qca8k_mii_write32(bus, 0x10 | r2, r1, val);
  100. + qca8k_mii_write32(priv, 0x10 | r2, r1, val);
  101. ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
  102. QCA8K_MDIO_MASTER_BUSY);
  103. exit:
  104. /* even if the busy_wait timeouts try to clear the MASTER_EN */
  105. - qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
  106. + qca8k_mii_write32(priv, 0x10 | r2, r1, 0);
  107. mutex_unlock(&bus->mdio_lock);
  108. @@ -1154,7 +1189,7 @@ qca8k_mdio_read(struct qca8k_priv *priv,
  109. if (ret)
  110. goto exit;
  111. - qca8k_mii_write32(bus, 0x10 | r2, r1, val);
  112. + qca8k_mii_write32(priv, 0x10 | r2, r1, val);
  113. ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
  114. QCA8K_MDIO_MASTER_BUSY);
  115. @@ -1165,7 +1200,7 @@ qca8k_mdio_read(struct qca8k_priv *priv,
  116. exit:
  117. /* even if the busy_wait timeouts try to clear the MASTER_EN */
  118. - qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
  119. + qca8k_mii_write32(priv, 0x10 | r2, r1, 0);
  120. mutex_unlock(&bus->mdio_lock);
  121. @@ -3038,6 +3073,8 @@ qca8k_sw_probe(struct mdio_device *mdiod
  122. }
  123. priv->mdio_cache.page = 0xffff;
  124. + priv->mdio_cache.lo = 0xffff;
  125. + priv->mdio_cache.hi = 0xffff;
  126. /* Check the detected switch id */
  127. ret = qca8k_read_switch_id(priv);
  128. --- a/drivers/net/dsa/qca8k.h
  129. +++ b/drivers/net/dsa/qca8k.h
  130. @@ -369,6 +369,11 @@ struct qca8k_mdio_cache {
  131. * mdio writes
  132. */
  133. u16 page;
  134. +/* lo and hi can also be cached and from Documentation we can skip one
  135. + * extra mdio write if lo or hi is didn't change.
  136. + */
  137. + u16 lo;
  138. + u16 hi;
  139. };
  140. struct qca8k_priv {