701-v6.2-0011-net-dpaa2-switch-serialize-changes-to-priv-mac-with.patch 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. From 80d12452a5f160c39d63efc1be07df36f9d07133 Mon Sep 17 00:00:00 2001
  2. From: Vladimir Oltean <[email protected]>
  3. Date: Tue, 29 Nov 2022 16:12:20 +0200
  4. Subject: [PATCH 13/14] net: dpaa2-switch: serialize changes to priv->mac with
  5. a mutex
  6. The dpaa2-switch driver uses a DPMAC in the same way as the dpaa2-eth
  7. driver, so we need to duplicate the locking solution established by the
  8. previous change to the switch driver as well.
  9. Signed-off-by: Vladimir Oltean <[email protected]>
  10. Reviewed-by: Ioana Ciornei <[email protected]>
  11. Tested-by: Ioana Ciornei <[email protected]>
  12. Signed-off-by: Paolo Abeni <[email protected]>
  13. ---
  14. .../freescale/dpaa2/dpaa2-switch-ethtool.c | 32 +++++++++++++++----
  15. .../ethernet/freescale/dpaa2/dpaa2-switch.c | 31 ++++++++++++++++--
  16. .../ethernet/freescale/dpaa2/dpaa2-switch.h | 2 ++
  17. 3 files changed, 55 insertions(+), 10 deletions(-)
  18. --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
  19. +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
  20. @@ -60,11 +60,18 @@ dpaa2_switch_get_link_ksettings(struct n
  21. {
  22. struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  23. struct dpsw_link_state state = {0};
  24. - int err = 0;
  25. + int err;
  26. - if (dpaa2_switch_port_is_type_phy(port_priv))
  27. - return phylink_ethtool_ksettings_get(port_priv->mac->phylink,
  28. - link_ksettings);
  29. + mutex_lock(&port_priv->mac_lock);
  30. +
  31. + if (dpaa2_switch_port_is_type_phy(port_priv)) {
  32. + err = phylink_ethtool_ksettings_get(port_priv->mac->phylink,
  33. + link_ksettings);
  34. + mutex_unlock(&port_priv->mac_lock);
  35. + return err;
  36. + }
  37. +
  38. + mutex_unlock(&port_priv->mac_lock);
  39. err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
  40. port_priv->ethsw_data->dpsw_handle,
  41. @@ -99,9 +106,16 @@ dpaa2_switch_set_link_ksettings(struct n
  42. bool if_running;
  43. int err = 0, ret;
  44. - if (dpaa2_switch_port_is_type_phy(port_priv))
  45. - return phylink_ethtool_ksettings_set(port_priv->mac->phylink,
  46. - link_ksettings);
  47. + mutex_lock(&port_priv->mac_lock);
  48. +
  49. + if (dpaa2_switch_port_is_type_phy(port_priv)) {
  50. + err = phylink_ethtool_ksettings_set(port_priv->mac->phylink,
  51. + link_ksettings);
  52. + mutex_unlock(&port_priv->mac_lock);
  53. + return err;
  54. + }
  55. +
  56. + mutex_unlock(&port_priv->mac_lock);
  57. /* Interface needs to be down to change link settings */
  58. if_running = netif_running(netdev);
  59. @@ -189,8 +203,12 @@ static void dpaa2_switch_ethtool_get_sta
  60. dpaa2_switch_ethtool_counters[i].name, err);
  61. }
  62. + mutex_lock(&port_priv->mac_lock);
  63. +
  64. if (dpaa2_switch_port_has_mac(port_priv))
  65. dpaa2_mac_get_ethtool_stats(port_priv->mac, data + i);
  66. +
  67. + mutex_unlock(&port_priv->mac_lock);
  68. }
  69. const struct ethtool_ops dpaa2_switch_port_ethtool_ops = {
  70. --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
  71. +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
  72. @@ -603,8 +603,11 @@ static int dpaa2_switch_port_link_state_
  73. /* When we manage the MAC/PHY using phylink there is no need
  74. * to manually update the netif_carrier.
  75. + * We can avoid locking because we are called from the "link changed"
  76. + * IRQ handler, which is the same as the "endpoint changed" IRQ handler
  77. + * (the writer to port_priv->mac), so we cannot race with it.
  78. */
  79. - if (dpaa2_switch_port_is_type_phy(port_priv))
  80. + if (dpaa2_mac_is_type_phy(port_priv->mac))
  81. return 0;
  82. /* Interrupts are received even though no one issued an 'ifconfig up'
  83. @@ -684,6 +687,8 @@ static int dpaa2_switch_port_open(struct
  84. struct ethsw_core *ethsw = port_priv->ethsw_data;
  85. int err;
  86. + mutex_lock(&port_priv->mac_lock);
  87. +
  88. if (!dpaa2_switch_port_is_type_phy(port_priv)) {
  89. /* Explicitly set carrier off, otherwise
  90. * netif_carrier_ok() will return true and cause 'ip link show'
  91. @@ -697,6 +702,7 @@ static int dpaa2_switch_port_open(struct
  92. port_priv->ethsw_data->dpsw_handle,
  93. port_priv->idx);
  94. if (err) {
  95. + mutex_unlock(&port_priv->mac_lock);
  96. netdev_err(netdev, "dpsw_if_enable err %d\n", err);
  97. return err;
  98. }
  99. @@ -706,6 +712,8 @@ static int dpaa2_switch_port_open(struct
  100. if (dpaa2_switch_port_is_type_phy(port_priv))
  101. dpaa2_mac_start(port_priv->mac);
  102. + mutex_unlock(&port_priv->mac_lock);
  103. +
  104. return 0;
  105. }
  106. @@ -715,6 +723,8 @@ static int dpaa2_switch_port_stop(struct
  107. struct ethsw_core *ethsw = port_priv->ethsw_data;
  108. int err;
  109. + mutex_lock(&port_priv->mac_lock);
  110. +
  111. if (dpaa2_switch_port_is_type_phy(port_priv)) {
  112. dpaa2_mac_stop(port_priv->mac);
  113. } else {
  114. @@ -722,6 +732,8 @@ static int dpaa2_switch_port_stop(struct
  115. netif_carrier_off(netdev);
  116. }
  117. + mutex_unlock(&port_priv->mac_lock);
  118. +
  119. err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0,
  120. port_priv->ethsw_data->dpsw_handle,
  121. port_priv->idx);
  122. @@ -1461,7 +1473,9 @@ static int dpaa2_switch_port_connect_mac
  123. }
  124. }
  125. + mutex_lock(&port_priv->mac_lock);
  126. port_priv->mac = mac;
  127. + mutex_unlock(&port_priv->mac_lock);
  128. return 0;
  129. @@ -1474,9 +1488,12 @@ err_free_mac:
  130. static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
  131. {
  132. - struct dpaa2_mac *mac = port_priv->mac;
  133. + struct dpaa2_mac *mac;
  134. + mutex_lock(&port_priv->mac_lock);
  135. + mac = port_priv->mac;
  136. port_priv->mac = NULL;
  137. + mutex_unlock(&port_priv->mac_lock);
  138. if (!mac)
  139. return;
  140. @@ -1495,6 +1512,7 @@ static irqreturn_t dpaa2_switch_irq0_han
  141. struct ethsw_port_priv *port_priv;
  142. u32 status = ~0;
  143. int err, if_id;
  144. + bool had_mac;
  145. err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
  146. DPSW_IRQ_INDEX_IF, &status);
  147. @@ -1513,7 +1531,12 @@ static irqreturn_t dpaa2_switch_irq0_han
  148. if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
  149. rtnl_lock();
  150. - if (dpaa2_switch_port_has_mac(port_priv))
  151. + /* We can avoid locking because the "endpoint changed" IRQ
  152. + * handler is the only one who changes priv->mac at runtime,
  153. + * so we are not racing with anyone.
  154. + */
  155. + had_mac = !!port_priv->mac;
  156. + if (had_mac)
  157. dpaa2_switch_port_disconnect_mac(port_priv);
  158. else
  159. dpaa2_switch_port_connect_mac(port_priv);
  160. @@ -3256,6 +3279,8 @@ static int dpaa2_switch_probe_port(struc
  161. port_priv->netdev = port_netdev;
  162. port_priv->ethsw_data = ethsw;
  163. + mutex_init(&port_priv->mac_lock);
  164. +
  165. port_priv->idx = port_idx;
  166. port_priv->stp_state = BR_STATE_FORWARDING;
  167. --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
  168. +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
  169. @@ -161,6 +161,8 @@ struct ethsw_port_priv {
  170. struct dpaa2_switch_filter_block *filter_block;
  171. struct dpaa2_mac *mac;
  172. + /* Protects against changes to port_priv->mac */
  173. + struct mutex mac_lock;
  174. };
  175. /* Switch data */