forked from mirror/openwrt
mac80211: backport upstream patches
Will be used by an upcoming mt76 update Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
0fa94cff86
commit
c4229e76f3
2 changed files with 250 additions and 0 deletions
|
|
@ -0,0 +1,148 @@
|
|||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Thu, 8 Jan 2026 14:34:31 +0100
|
||||
Subject: [PATCH] wifi: mac80211: improve interface iteration ergonomics
|
||||
|
||||
Right now, the only way to iterate interfaces is to declare an
|
||||
iterator function, possibly data structure to use, and pass all
|
||||
that to the iteration helper function. This is annoying, and
|
||||
there's really no inherent need for it, except it was easier to
|
||||
implement with the iflist mutex, but that's not used much now.
|
||||
|
||||
Add a new for_each_interface() macro that does the iteration in
|
||||
a more ergonomic way. To avoid even more exported functions, do
|
||||
the old ieee80211_iterate_active_interfaces_mtx() as an inline
|
||||
using the new way, which may also let the compiler optimise it
|
||||
a bit more, e.g. via inlining the iterator function.
|
||||
|
||||
Also provide for_each_active_interface() for the common case of
|
||||
just iterating active interfaces.
|
||||
|
||||
Link: https://patch.msgid.link/20260108143431.f2581e0c381a.Ie387227504c975c109c125b3c57f0bb3fdab2835@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -6270,6 +6270,30 @@ void ieee80211_iterate_active_interfaces
|
||||
struct ieee80211_vif *vif),
|
||||
void *data);
|
||||
|
||||
+struct ieee80211_vif *
|
||||
+__ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *prev,
|
||||
+ u32 iter_flags);
|
||||
+
|
||||
+/**
|
||||
+ * for_each_interface - iterate interfaces under wiphy mutex
|
||||
+ * @vif: the iterator variable
|
||||
+ * @hw: the HW to iterate for
|
||||
+ * @flags: the iteration flags, see &enum ieee80211_interface_iteration_flags
|
||||
+ */
|
||||
+#define for_each_interface(vif, hw, flags) \
|
||||
+ for (vif = __ieee80211_iterate_interfaces(hw, NULL, flags); \
|
||||
+ vif; \
|
||||
+ vif = __ieee80211_iterate_interfaces(hw, vif, flags))
|
||||
+
|
||||
+/**
|
||||
+ * for_each_active_interface - iterate active interfaces under wiphy mutex
|
||||
+ * @vif: the iterator variable
|
||||
+ * @hw: the HW to iterate for
|
||||
+ */
|
||||
+#define for_each_active_interface(vif, hw) \
|
||||
+ for_each_interface(vif, hw, IEEE80211_IFACE_ITER_ACTIVE)
|
||||
+
|
||||
/**
|
||||
* ieee80211_iterate_active_interfaces_mtx - iterate active interfaces
|
||||
*
|
||||
@@ -6282,12 +6306,18 @@ void ieee80211_iterate_active_interfaces
|
||||
* @iterator: the iterator function to call, cannot sleep
|
||||
* @data: first argument of the iterator function
|
||||
*/
|
||||
-void ieee80211_iterate_active_interfaces_mtx(struct ieee80211_hw *hw,
|
||||
- u32 iter_flags,
|
||||
- void (*iterator)(void *data,
|
||||
- u8 *mac,
|
||||
- struct ieee80211_vif *vif),
|
||||
- void *data);
|
||||
+static inline void
|
||||
+ieee80211_iterate_active_interfaces_mtx(struct ieee80211_hw *hw,
|
||||
+ u32 iter_flags,
|
||||
+ void (*iterator)(void *data, u8 *mac,
|
||||
+ struct ieee80211_vif *vif),
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct ieee80211_vif *vif;
|
||||
+
|
||||
+ for_each_interface(vif, hw, iter_flags | IEEE80211_IFACE_ITER_ACTIVE)
|
||||
+ iterator(data, vif->addr, vif);
|
||||
+}
|
||||
|
||||
/**
|
||||
* ieee80211_iterate_stations_atomic - iterate stations
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -800,20 +800,56 @@ void ieee80211_iterate_active_interfaces
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
|
||||
|
||||
-void ieee80211_iterate_active_interfaces_mtx(
|
||||
- struct ieee80211_hw *hw, u32 iter_flags,
|
||||
- void (*iterator)(void *data, u8 *mac,
|
||||
- struct ieee80211_vif *vif),
|
||||
- void *data)
|
||||
+struct ieee80211_vif *
|
||||
+__ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *prev,
|
||||
+ u32 iter_flags)
|
||||
{
|
||||
+ bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE;
|
||||
+ struct ieee80211_sub_if_data *sdata = NULL, *monitor;
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
lockdep_assert_wiphy(hw->wiphy);
|
||||
|
||||
- __iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
|
||||
- iterator, data);
|
||||
+ if (prev)
|
||||
+ sdata = vif_to_sdata(prev);
|
||||
+
|
||||
+ monitor = rcu_dereference_check(local->monitor_sdata,
|
||||
+ lockdep_is_held(&hw->wiphy->mtx));
|
||||
+ if (monitor && monitor == sdata)
|
||||
+ return NULL;
|
||||
+
|
||||
+ sdata = list_prepare_entry(sdata, &local->interfaces, list);
|
||||
+ list_for_each_entry_continue(sdata, &local->interfaces, list) {
|
||||
+ switch (sdata->vif.type) {
|
||||
+ case NL80211_IFTYPE_MONITOR:
|
||||
+ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
|
||||
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case NL80211_IFTYPE_AP_VLAN:
|
||||
+ continue;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
|
||||
+ active_only && !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
|
||||
+ continue;
|
||||
+ if ((iter_flags & IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) &&
|
||||
+ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
|
||||
+ continue;
|
||||
+ if (ieee80211_sdata_running(sdata) || !active_only)
|
||||
+ return &sdata->vif;
|
||||
+ }
|
||||
+
|
||||
+ if (monitor && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
|
||||
+ (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
|
||||
+ monitor->flags & IEEE80211_SDATA_IN_DRIVER))
|
||||
+ return &monitor->vif;
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_mtx);
|
||||
+EXPORT_SYMBOL_GPL(__ieee80211_iterate_interfaces);
|
||||
|
||||
static void __iterate_stations(struct ieee80211_local *local,
|
||||
void (*iterator)(void *data,
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Thu, 8 Jan 2026 14:34:32 +0100
|
||||
Subject: [PATCH] wifi: mac80211: improve station iteration ergonomics
|
||||
|
||||
Right now, the only way to iterate stations is to declare an
|
||||
iterator function, possibly data structure to use, and pass all
|
||||
that to the iteration helper function. This is annoying, and
|
||||
there's really no inherent need for it.
|
||||
|
||||
Add a new for_each_station() macro that does the iteration in
|
||||
a more ergonomic way. To avoid even more exported functions, do
|
||||
the old ieee80211_iterate_stations_mtx() as an inline using the
|
||||
new way, which may also let the compiler optimise it a bit more,
|
||||
e.g. via inlining the iterator function.
|
||||
|
||||
Link: https://patch.msgid.link/20260108143431.d2b641f6f6af.I4470024f7404446052564b15bcf8b3f1ada33655@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -6336,6 +6336,20 @@ void ieee80211_iterate_stations_atomic(s
|
||||
struct ieee80211_sta *sta),
|
||||
void *data);
|
||||
|
||||
+struct ieee80211_sta *
|
||||
+__ieee80211_iterate_stations(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_sta *prev);
|
||||
+
|
||||
+/**
|
||||
+ * for_each_station - iterate stations under wiphy mutex
|
||||
+ * @sta: the iterator variable
|
||||
+ * @hw: the HW to iterate for
|
||||
+ */
|
||||
+#define for_each_station(sta, hw) \
|
||||
+ for (sta = __ieee80211_iterate_stations(hw, NULL); \
|
||||
+ sta; \
|
||||
+ sta = __ieee80211_iterate_stations(hw, sta))
|
||||
+
|
||||
/**
|
||||
* ieee80211_iterate_stations_mtx - iterate stations
|
||||
*
|
||||
@@ -6348,10 +6362,17 @@ void ieee80211_iterate_stations_atomic(s
|
||||
* @iterator: the iterator function to call
|
||||
* @data: first argument of the iterator function
|
||||
*/
|
||||
-void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw,
|
||||
- void (*iterator)(void *data,
|
||||
- struct ieee80211_sta *sta),
|
||||
- void *data);
|
||||
+static inline void
|
||||
+ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw,
|
||||
+ void (*iterator)(void *data,
|
||||
+ struct ieee80211_sta *sta),
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct ieee80211_sta *sta;
|
||||
+
|
||||
+ for_each_station(sta, hw)
|
||||
+ iterator(data, sta);
|
||||
+}
|
||||
|
||||
/**
|
||||
* ieee80211_queue_work - add work onto the mac80211 workqueue
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -880,18 +880,29 @@ void ieee80211_iterate_stations_atomic(s
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
|
||||
|
||||
-void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw,
|
||||
- void (*iterator)(void *data,
|
||||
- struct ieee80211_sta *sta),
|
||||
- void *data)
|
||||
+struct ieee80211_sta *
|
||||
+__ieee80211_iterate_stations(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_sta *prev)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ struct sta_info *sta = NULL;
|
||||
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
- __iterate_stations(local, iterator, data);
|
||||
+ if (prev)
|
||||
+ sta = container_of(prev, struct sta_info, sta);
|
||||
+
|
||||
+ sta = list_prepare_entry(sta, &local->sta_list, list);
|
||||
+ list_for_each_entry_continue(sta, &local->sta_list, list) {
|
||||
+ if (!sta->uploaded)
|
||||
+ continue;
|
||||
+
|
||||
+ return &sta->sta;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_mtx);
|
||||
+EXPORT_SYMBOL_GPL(__ieee80211_iterate_stations);
|
||||
|
||||
struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
|
||||
{
|
||||
Loading…
Add table
Reference in a new issue