765-v5.17-04-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. From c146f9bc195a9dc3ad7fd000a14540e7c9df952d Mon Sep 17 00:00:00 2001
  2. From: Vladimir Oltean <[email protected]>
  3. Date: Thu, 6 Jan 2022 01:11:15 +0200
  4. Subject: [PATCH 4/6] net: dsa: hold rtnl_mutex when calling
  5. dsa_master_{setup,teardown}
  6. DSA needs to simulate master tracking events when a binding is first
  7. with a DSA master established and torn down, in order to give drivers
  8. the simplifying guarantee that ->master_state_change calls are made
  9. only when the master's readiness state to pass traffic changes.
  10. master_state_change() provide a operational bool that DSA driver can use
  11. to understand if DSA master is operational or not.
  12. To avoid races, we need to block the reception of
  13. NETDEV_UP/NETDEV_CHANGE/NETDEV_GOING_DOWN events in the netdev notifier
  14. chain while we are changing the master's dev->dsa_ptr (this changes what
  15. netdev_uses_dsa(dev) reports).
  16. The dsa_master_setup() and dsa_master_teardown() functions optionally
  17. require the rtnl_mutex to be held, if the tagger needs the master to be
  18. promiscuous, these functions call dev_set_promiscuity(). Move the
  19. rtnl_lock() from that function and make it top-level.
  20. Signed-off-by: Vladimir Oltean <[email protected]>
  21. Reviewed-by: Florian Fainelli <[email protected]>
  22. Signed-off-by: David S. Miller <[email protected]>
  23. ---
  24. net/dsa/dsa2.c | 8 ++++++++
  25. net/dsa/master.c | 4 ++--
  26. 2 files changed, 10 insertions(+), 2 deletions(-)
  27. --- a/net/dsa/dsa2.c
  28. +++ b/net/dsa/dsa2.c
  29. @@ -1034,6 +1034,8 @@ static int dsa_tree_setup_master(struct
  30. struct dsa_port *dp;
  31. int err;
  32. + rtnl_lock();
  33. +
  34. list_for_each_entry(dp, &dst->ports, list) {
  35. if (dsa_port_is_cpu(dp)) {
  36. err = dsa_master_setup(dp->master, dp);
  37. @@ -1042,6 +1044,8 @@ static int dsa_tree_setup_master(struct
  38. }
  39. }
  40. + rtnl_unlock();
  41. +
  42. return 0;
  43. }
  44. @@ -1049,9 +1053,13 @@ static void dsa_tree_teardown_master(str
  45. {
  46. struct dsa_port *dp;
  47. + rtnl_lock();
  48. +
  49. list_for_each_entry(dp, &dst->ports, list)
  50. if (dsa_port_is_cpu(dp))
  51. dsa_master_teardown(dp->master);
  52. +
  53. + rtnl_unlock();
  54. }
  55. static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
  56. --- a/net/dsa/master.c
  57. +++ b/net/dsa/master.c
  58. @@ -266,9 +266,9 @@ static void dsa_master_set_promiscuity(s
  59. if (!ops->promisc_on_master)
  60. return;
  61. - rtnl_lock();
  62. + ASSERT_RTNL();
  63. +
  64. dev_set_promiscuity(dev, inc);
  65. - rtnl_unlock();
  66. }
  67. static ssize_t tagging_show(struct device *d, struct device_attribute *attr,