diff mbox

[virtual-sta,1/3] mac80211: Add more general interface iterator.

Message ID 1284156298-15863-1-git-send-email-greearb@candelatech.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Ben Greear Sept. 10, 2010, 10:04 p.m. UTC
None
diff mbox

Patch

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f91fc33..53e5d5b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -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
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index bd40b11..ad96d5f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -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);