wifi: mac80211: add vif/sta link RCU dereference macros
authorJohannes Berg <johannes.berg@intel.com>
Fri, 2 Sep 2022 14:12:52 +0000 (16:12 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Sep 2022 08:14:45 +0000 (10:14 +0200)
Add macros (and an exported function) to allow checking some
link RCU protected accesses that are happening in callbacks
from mac80211 and are thus under the correct lock.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/mac80211_hwsim.c
include/net/mac80211.h
net/mac80211/sta_info.c

index 7bbc455..0780a1c 100644 (file)
@@ -3069,8 +3069,7 @@ static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw,
        for_each_set_bit(i, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
                struct ieee80211_bss_conf *link_conf;
 
-               /* FIXME: figure out how to get the locking here */
-               link_conf = rcu_dereference_protected(vif->link_conf[i], 1);
+               link_conf = link_conf_dereference_protected(vif, i);
                if (WARN_ON(!link_conf))
                        continue;
 
index bfa6a16..d9e7f62 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/ieee80211.h>
+#include <linux/lockdep.h>
 #include <net/cfg80211.h>
 #include <net/codel.h>
 #include <net/ieee80211_radiotap.h>
@@ -1902,6 +1903,19 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
 struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif);
 
 /**
+ * lockdep_vif_mutex_held - for lockdep checks on link poiners
+ * @vif: the interface to check
+ */
+static inline bool lockdep_vif_mutex_held(struct ieee80211_vif *vif)
+{
+       return lockdep_is_held(&ieee80211_vif_to_wdev(vif)->mtx);
+}
+
+#define link_conf_dereference_protected(vif, link_id)          \
+       rcu_dereference_protected((vif)->link_conf[link_id],    \
+                                 lockdep_vif_mutex_held(vif))
+
+/**
  * enum ieee80211_key_flags - key flags
  *
  * These flags are used for communication about keys between the driver
@@ -2266,13 +2280,24 @@ struct ieee80211_sta {
        u8 drv_priv[] __aligned(sizeof(void *));
 };
 
-/* FIXME: check the locking correctly */
+#ifdef CONFIG_LOCKDEP
+bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta);
+#else
+static inline bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta)
+{
+       return true;
+}
+#endif
+
+#define link_sta_dereference_protected(sta, link_id)           \
+       rcu_dereference_protected((sta)->link[link_id],         \
+                                 lockdep_sta_mutex_held(sta))
+
 #define for_each_sta_active_link(vif, sta, link_sta, link_id)                  \
        for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++)         \
                if ((!(vif)->active_links ||                                    \
                     (vif)->active_links & BIT(link_id)) &&                     \
-                   ((link_sta) = rcu_dereference_protected((sta)->link[link_id],\
-                                                           1)))
+                   ((link_sta) = link_sta_dereference_protected(sta, link_id)))
 
 /**
  * enum sta_notify_cmd - sta notify command
index bbf582a..4875bd8 100644 (file)
@@ -2871,3 +2871,13 @@ void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
        if (val)
                sta->sta.max_amsdu_subframes = 4 << val;
 }
+
+#ifdef CONFIG_LOCKDEP
+bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta)
+{
+       struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+
+       return lockdep_is_held(&sta->local->sta_mtx);
+}
+EXPORT_SYMBOL(lockdep_sta_mutex_held);
+#endif