781-v6.6-02-net-dsa-qca8k-fix-potential-MDIO-bus-conflict-when-a.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. From 526c8ee04bdbd4d8d19a583b1f3b06700229a815 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <[email protected]>
  3. Date: Wed, 4 Oct 2023 11:19:04 +0200
  4. Subject: [PATCH 2/2] net: dsa: qca8k: fix potential MDIO bus conflict when
  5. accessing internal PHYs via management frames
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. Besides the QCA8337 switch the Turris 1.x device has on it's MDIO bus
  10. also Micron ethernet PHY (dedicated to the WAN port).
  11. We've been experiencing a strange behavior of the WAN ethernet
  12. interface, wherein the WAN PHY started timing out the MDIO accesses, for
  13. example when the interface was brought down and then back up.
  14. Bisecting led to commit 2cd548566384 ("net: dsa: qca8k: add support for
  15. phy read/write with mgmt Ethernet"), which added support to access the
  16. QCA8337 switch's internal PHYs via management ethernet frames.
  17. Connecting the MDIO bus pins onto an oscilloscope, I was able to see
  18. that the MDIO bus was active whenever a request to read/write an
  19. internal PHY register was done via an management ethernet frame.
  20. My theory is that when the switch core always communicates with the
  21. internal PHYs via the MDIO bus, even when externally we request the
  22. access via ethernet. This MDIO bus is the same one via which the switch
  23. and internal PHYs are accessible to the board, and the board may have
  24. other devices connected on this bus. An ASCII illustration may give more
  25. insight:
  26. +---------+
  27. +----| |
  28. | | WAN PHY |
  29. | +--| |
  30. | | +---------+
  31. | |
  32. | | +----------------------------------+
  33. | | | QCA8337 |
  34. MDC | | | +-------+ |
  35. ------o-+--|--------o------------o--| | |
  36. MDIO | | | | | PHY 1 |-|--to RJ45
  37. --------o--|---o----+---------o--+--| | |
  38. | | | | | +-------+ |
  39. | +-------------+ | o--| | |
  40. | | MDIO MDC | | | | PHY 2 |-|--to RJ45
  41. eth1 | | | o--+--| | |
  42. -----------|-|port0 | | | +-------+ |
  43. | | | | o--| | |
  44. | | switch core | | | | PHY 3 |-|--to RJ45
  45. | +-------------+ o--+--| | |
  46. | | | +-------+ |
  47. | | o--| ... | |
  48. +----------------------------------+
  49. When we send a request to read an internal PHY register via an ethernet
  50. management frame via eth1, the switch core receives the ethernet frame
  51. on port 0 and then communicates with the internal PHY via MDIO. At this
  52. time, other potential devices, such as the WAN PHY on Turris 1.x, cannot
  53. use the MDIO bus, since it may cause a bus conflict.
  54. Fix this issue by locking the MDIO bus even when we are accessing the
  55. PHY registers via ethernet management frames.
  56. Fixes: 2cd548566384 ("net: dsa: qca8k: add support for phy read/write with mgmt Ethernet")
  57. Signed-off-by: Marek Behún <[email protected]>
  58. Reviewed-by: Christian Marangi <[email protected]>
  59. Signed-off-by: David S. Miller <[email protected]>
  60. ---
  61. drivers/net/dsa/qca/qca8k-8xxx.c | 11 +++++++++++
  62. 1 file changed, 11 insertions(+)
  63. --- a/drivers/net/dsa/qca/qca8k-8xxx.c
  64. +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
  65. @@ -665,6 +665,15 @@ qca8k_phy_eth_command(struct qca8k_priv
  66. goto err_read_skb;
  67. }
  68. + /* It seems that accessing the switch's internal PHYs via management
  69. + * packets still uses the MDIO bus within the switch internally, and
  70. + * these accesses can conflict with external MDIO accesses to other
  71. + * devices on the MDIO bus.
  72. + * We therefore need to lock the MDIO bus onto which the switch is
  73. + * connected.
  74. + */
  75. + mutex_lock(&priv->bus->mdio_lock);
  76. +
  77. /* Actually start the request:
  78. * 1. Send mdio master packet
  79. * 2. Busy Wait for mdio master command
  80. @@ -677,6 +686,7 @@ qca8k_phy_eth_command(struct qca8k_priv
  81. mgmt_master = priv->mgmt_master;
  82. if (!mgmt_master) {
  83. mutex_unlock(&mgmt_eth_data->mutex);
  84. + mutex_unlock(&priv->bus->mdio_lock);
  85. ret = -EINVAL;
  86. goto err_mgmt_master;
  87. }
  88. @@ -764,6 +774,7 @@ exit:
  89. QCA8K_ETHERNET_TIMEOUT);
  90. mutex_unlock(&mgmt_eth_data->mutex);
  91. + mutex_unlock(&priv->bus->mdio_lock);
  92. return ret;