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
*
* @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
}
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,