From: Johannes Berg <johannes.berg@xxxxxxxxx> 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@xxxxxxxxx> --- drivers/net/wireless/mac80211_hwsim.c | 3 +-- include/net/mac80211.h | 31 ++++++++++++++++++++++++--- net/mac80211/sta_info.c | 10 +++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index f464d3507fe9..f044db1621dd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -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; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bfa6a1625c5c..d9e7f62cc972 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -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> @@ -1901,6 +1902,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 * @@ -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 diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 1749c21e735c..baa55fbab0a2 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -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 -- 2.37.2