@@ -2320,6 +2320,30 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
u8 *mac,
struct ieee80211_vif *vif),
void *data);
+/**
+ * ieee80211_iterate_interfaces_helper - iterate interfaces
+ *
+ * This function iterates over the interfaces associated with a given
+ * hardware and calls the callback for them. If do_atomic is true,
+ * this function requires the iterator callback function to be atomic,
+ * if that is not desired, set do_atomic to false.
+ * If you want only active interfaces, set active_only to true.
+ * See also: @ieee80211_iterate_active_interfaces
+ * @ieee80211_iterate_active_interfaces_atomic
+ *
+ * Returns number of interfaces to be filtered.
+ * @hw: the hardware struct of which the interfaces should be iterated over
+ * @do_atomic: Should iterator be treated as atomic or not.
+ * @active_only: Should we only iterate over active interfaces.
+ * @iterator: the iterator function to call, cannot sleep
+ * @data: first argument of the iterator function
+ */
+int ieee80211_iterate_interfaces_helper(struct ieee80211_hw *hw,
+ bool do_atomic,
+ bool active_only,
+ void (*iterator)(void *data, u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data);
/**
* ieee80211_queue_work - add work onto the mac80211 workqueue
@@ -461,71 +461,85 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_wake_queues);
-void ieee80211_iterate_active_interfaces(
- struct ieee80211_hw *hw,
+static int _iter_loop_helper(
+ struct ieee80211_sub_if_data *sdata,
+ bool active_only,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data)
{
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata;
-
- mutex_lock(&local->iflist_mtx);
-
- list_for_each_entry(sdata, &local->interfaces, list) {
- switch (sdata->vif.type) {
- case NUM_NL80211_IFTYPES:
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_AP_VLAN:
- continue;
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_WDS:
- case NL80211_IFTYPE_MESH_POINT:
- break;
- }
- if (ieee80211_sdata_running(sdata))
+ switch (sdata->vif.type) {
+ case NUM_NL80211_IFTYPES:
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_AP_VLAN:
+ return 0;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ }
+ if (ieee80211_sdata_running(sdata) || !active_only) {
+ if (iterator)
iterator(data, sdata->vif.addr,
&sdata->vif);
+ return 1;
}
-
- mutex_unlock(&local->iflist_mtx);
+ return 0;
}
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
-void ieee80211_iterate_active_interfaces_atomic(
+int ieee80211_iterate_interfaces_helper(
struct ieee80211_hw *hw,
+ bool do_atomic,
+ bool active_only,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
+ int cnt = 0;
- rcu_read_lock();
+ if (do_atomic) {
+ rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- switch (sdata->vif.type) {
- case NUM_NL80211_IFTYPES:
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_AP_VLAN:
- continue;
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_WDS:
- case NL80211_IFTYPE_MESH_POINT:
- break;
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ cnt += _iter_loop_helper(sdata, active_only,
+ iterator, data);
}
- if (ieee80211_sdata_running(sdata))
- iterator(data, sdata->vif.addr,
- &sdata->vif);
+ rcu_read_unlock();
+ } else {
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ cnt += _iter_loop_helper(sdata, active_only,
+ iterator, data);
+ }
+ mutex_unlock(&local->iflist_mtx);
}
+ return cnt;
+}
+EXPORT_SYMBOL_GPL(ieee80211_iterate_interfaces_helper);
- rcu_read_unlock();
+
+void ieee80211_iterate_active_interfaces(
+ struct ieee80211_hw *hw,
+ void (*iterator)(void *data, u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data)
+{
+ ieee80211_iterate_interfaces_helper(hw, false, false, iterator, data);
+}
+EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
+
+void ieee80211_iterate_active_interfaces_atomic(
+ struct ieee80211_hw *hw,
+ void (*iterator)(void *data, u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data)
+{
+ ieee80211_iterate_interfaces_helper(hw, true, false, iterator, data);
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);