]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: Add link iteration macro for link data with rcu_dereference
authorMaharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Fri, 18 Jul 2025 06:08:35 +0000 (11:38 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 18 Jul 2025 12:08:11 +0000 (14:08 +0200)
Currently, the existing macro for_each_link_data() uses sdata_dereference()
which requires the wiphy lock. This lock cannot be used in atomic or RCU
read-side contexts, such as in the RX path.

Introduce a new macro, for_each_link_data_rcu(), that iterates over link of
sdata using rcu_dereference(), making it safe to use in RCU contexts. This
allows callers to access link data without requiring the wiphy lock.

The macro takes into account the vif.valid_links bitmap and ensures only
valid links are accessed safely. Callers are responsible for ensuring that
rcu_read_lock() is held when using this macro.

Signed-off-by: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250718060837.59371-3-maharaja.kennadyrajan@oss.qualcomm.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h

index 7c18c51966d0a476f2e55c8ec64d80db73a19293..9c0603eb580fc3a3338e7b56358a89c5ec44bc2d 100644 (file)
@@ -1252,6 +1252,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
                    ((__link) = sdata_dereference((__sdata)->link[__link_id],   \
                                                  (__sdata))))
 
+/*
+ * for_each_link_data_rcu should be used under RCU read lock.
+ */
+#define for_each_link_data_rcu(sdata, __link)                                  \
+       /* outer loop just to define the variable ... */                        \
+       for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata;          \
+               __sdata = NULL /* always stop */)                               \
+       for (int __link_id = 0;                                                 \
+            __link_id < ARRAY_SIZE((__sdata)->link); __link_id++)              \
+               if ((!(__sdata)->vif.valid_links ||                             \
+                    (__sdata)->vif.valid_links & BIT(__link_id)) &&            \
+                   ((__link) = rcu_dereference((__sdata)->link[__link_id])))   \
+
 static inline int
 ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems,
                                struct cfg80211_rnr_elems *rnr_elems,