Search Linux Wireless

[RFC 1/5] mac80211: make filter configuration work per subif

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


ieee80211_configure_filter takes ieee80211_sub_if_data*
as argument instead of ieee80211_local*.

reconfig_filter work is now bounded to ieee80211_sub_if_data.

Signed-off-by: Lukasz Kucharczyk <lukasz.kucharczyk@xxxxxxxxx>
---
 net/mac80211/cfg.c         |    6 +++---
 net/mac80211/ieee80211_i.h |   15 ++++++++-------
 net/mac80211/iface.c       |   31 ++++++++++++++++++++++---------
 net/mac80211/main.c        |   21 +++++++--------------
 net/mac80211/mesh.c        |    4 ++--
 net/mac80211/scan.c        |    8 +++++---
 net/mac80211/util.c        |    6 ++----
 7 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 85ac364..d3ae0df 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -69,7 +69,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 		sdata->u.mgd.use_4addr = params->use_4addr;
 
 	if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) {
-		struct ieee80211_local *local = sdata->local;
 
 		if (ieee80211_sdata_running(sdata)) {
 			/*
@@ -88,7 +87,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 			sdata->u.mntr_flags = *flags;
 			ieee80211_adjust_monitor_flags(sdata, 1);
 
-			ieee80211_configure_filter(local);
+			ieee80211_configure_filter(sdata);
 		} else {
 			/*
 			 * Because the interface is down, ieee80211_do_stop
@@ -2489,6 +2488,7 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
 					  u16 frame_type, bool reg)
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
 		return;
@@ -2498,7 +2498,7 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
 	else
 		local->probe_req_reg--;
 
-	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+	ieee80211_queue_work(&local->hw, &sdata->reconfig_filter);
 }
 
 static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e6cbf5b..78fc9cc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -723,6 +723,13 @@ struct ieee80211_sub_if_data {
 		struct dentry *default_mgmt_key;
 	} debugfs;
 #endif
+
+	/* protects the aggregated multicast list and filter calls */
+	spinlock_t filter_lock;
+
+	/* used for uploading changed mc list */
+	struct work_struct reconfig_filter;
+
 	/* must be last, dynamically sized area in this! */
 	struct ieee80211_vif vif;
 };
@@ -842,12 +849,6 @@ struct ieee80211_local {
 
 	bool wiphy_ciphers_allocated;
 
-	/* protects the aggregated multicast list and filter calls */
-	spinlock_t filter_lock;
-
-	/* used for uploading changed mc list */
-	struct work_struct reconfig_filter;
-
 	/* used to reconfigure hardware SM PS */
 	struct work_struct recalc_smps;
 
@@ -1171,7 +1172,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 				      u32 changed);
-void ieee80211_configure_filter(struct ieee80211_local *local);
+void ieee80211_configure_filter(struct ieee80211_sub_if_data *sdata);
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
 
 /* STA code */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 87aeb4f..059388b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -385,7 +385,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
 		}
 
 		ieee80211_adjust_monitor_flags(sdata, 1);
-		ieee80211_configure_filter(local);
+		ieee80211_configure_filter(sdata);
 
 		netif_carrier_on(dev);
 		break;
@@ -405,7 +405,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
 			local->fif_pspoll++;
 			local->fif_probe_req++;
 
-			ieee80211_configure_filter(local);
+			ieee80211_configure_filter(sdata);
 		} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 			local->fif_probe_req++;
 		}
@@ -566,13 +566,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 	}
 
 	netif_addr_lock_bh(sdata->dev);
-	spin_lock_bh(&local->filter_lock);
+	spin_lock_bh(&sdata->filter_lock);
 	__hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
 			 sdata->dev->addr_len);
-	spin_unlock_bh(&local->filter_lock);
+	spin_unlock_bh(&sdata->filter_lock);
 	netif_addr_unlock_bh(sdata->dev);
 
-	ieee80211_configure_filter(local);
+	ieee80211_configure_filter(sdata);
 
 	del_timer_sync(&local->dynamic_ps_timer);
 	cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -631,7 +631,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		}
 
 		ieee80211_adjust_monitor_flags(sdata, -1);
-		ieee80211_configure_filter(local);
+		ieee80211_configure_filter(sdata);
 		break;
 	default:
 		flush_work(&sdata->work);
@@ -741,10 +741,10 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
 			atomic_dec(&local->iff_promiscs);
 		sdata->flags ^= IEEE80211_SDATA_PROMISC;
 	}
-	spin_lock_bh(&local->filter_lock);
+	spin_lock_bh(&sdata->filter_lock);
 	__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
-	spin_unlock_bh(&local->filter_lock);
-	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+	spin_unlock_bh(&sdata->filter_lock);
+	ieee80211_queue_work(&local->hw, &sdata->reconfig_filter);
 }
 
 /*
@@ -960,6 +960,14 @@ static void ieee80211_iface_work(struct work_struct *work)
 	}
 }
 
+static void ieee80211_reconfig_filter(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     reconfig_filter);
+
+	ieee80211_configure_filter(sdata);
+}
 
 /*
  * Helper function to initialise an interface to a specific type.
@@ -984,8 +992,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	/* only monitor differs */
 	sdata->dev->type = ARPHRD_ETHER;
 
+	spin_lock_init(&sdata->filter_lock);
+
 	skb_queue_head_init(&sdata->skb_queue);
 	INIT_WORK(&sdata->work, ieee80211_iface_work);
+	INIT_WORK(&sdata->reconfig_filter, ieee80211_reconfig_filter);
 
 	switch (type) {
 	case NL80211_IFTYPE_P2P_GO:
@@ -1373,6 +1384,8 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
 {
 	ASSERT_RTNL();
 
+	cancel_work_sync(&sdata->reconfig_filter);
+
 	mutex_lock(&sdata->local->iflist_mtx);
 	list_del_rcu(&sdata->list);
 	mutex_unlock(&sdata->local->iflist_mtx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d81c178..14c990a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -35,11 +35,15 @@
 
 static struct lock_class_key ieee80211_rx_skb_queue_class;
 
-void ieee80211_configure_filter(struct ieee80211_local *local)
+void ieee80211_configure_filter(struct ieee80211_sub_if_data *sdata)
 {
 	u64 mc;
 	unsigned int changed_flags;
 	unsigned int new_flags = 0;
+	struct ieee80211_local *local = sdata->local;
+
+	if (!ieee80211_sdata_running(sdata))
+		return;
 
 	if (atomic_read(&local->iff_promiscs))
 		new_flags |= FIF_PROMISC_IN_BSS;
@@ -69,11 +73,11 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
 	if (local->fif_pspoll)
 		new_flags |= FIF_PSPOLL;
 
-	spin_lock_bh(&local->filter_lock);
+	spin_lock_bh(&sdata->filter_lock);
 	changed_flags = local->filter_flags ^ new_flags;
 
 	mc = drv_prepare_multicast(local, &local->mc_list);
-	spin_unlock_bh(&local->filter_lock);
+	spin_unlock_bh(&sdata->filter_lock);
 
 	/* be a bit nasty */
 	new_flags |= (1<<31);
@@ -85,14 +89,6 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
 	local->filter_flags = new_flags & ~(1<<31);
 }
 
-static void ieee80211_reconfig_filter(struct work_struct *work)
-{
-	struct ieee80211_local *local =
-		container_of(work, struct ieee80211_local, reconfig_filter);
-
-	ieee80211_configure_filter(local);
-}
-
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
 	struct ieee80211_channel *chan;
@@ -610,7 +606,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	mutex_init(&local->mtx);
 
 	mutex_init(&local->key_mtx);
-	spin_lock_init(&local->filter_lock);
 	spin_lock_init(&local->queue_stop_reason_lock);
 
 	/*
@@ -627,7 +622,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 
 	INIT_WORK(&local->restart_work, ieee80211_restart_work);
 
-	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
 	INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
 	local->smps_mode = IEEE80211_SMPS_OFF;
 
@@ -1015,7 +1009,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 	rtnl_unlock();
 
 	cancel_work_sync(&local->restart_work);
-	cancel_work_sync(&local->reconfig_filter);
 
 	ieee80211_clear_tx_pending(local);
 	rate_control_deinitialize(local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 7cf1950..94acc1c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -585,7 +585,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	local->fif_other_bss++;
 	/* mesh ifaces must set allmulti to forward mcast traffic */
 	atomic_inc(&local->iff_allmultis);
-	ieee80211_configure_filter(local);
+	ieee80211_configure_filter(sdata);
 
 	ifmsh->mesh_cc_id = 0;	/* Disabled */
 	ifmsh->mesh_auth_id = 0;	/* Disabled */
@@ -631,7 +631,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 
 	local->fif_other_bss--;
 	atomic_dec(&local->iff_allmultis);
-	ieee80211_configure_filter(local);
+	ieee80211_configure_filter(sdata);
 }
 
 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 379f178..9a2cba8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -277,6 +277,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 				       bool was_hw_scan)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
 
 	lockdep_assert_held(&local->mtx);
 
@@ -304,6 +305,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 	if (local->scan_req != local->int_scan_req)
 		cfg80211_scan_done(local->scan_req, aborted);
 	local->scan_req = NULL;
+	sdata = local->scan_sdata;
 	local->scan_sdata = NULL;
 
 	local->scanning = 0;
@@ -313,7 +315,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 	ieee80211_hw_config(local, 0);
 
 	if (!was_hw_scan) {
-		ieee80211_configure_filter(local);
+		ieee80211_configure_filter(sdata);
 		drv_sw_scan_complete(local);
 		ieee80211_offchannel_return(local, true);
 	}
@@ -362,7 +364,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 
 	ieee80211_offchannel_stop_vifs(local, true);
 
-	ieee80211_configure_filter(local);
+	ieee80211_configure_filter(local->scan_sdata);
 
 	/* We need to set power level at maximum rate for scanning. */
 	ieee80211_hw_config(local, 0);
@@ -494,7 +496,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 		 * same as normal software scan, in case that matters. */
 		drv_sw_scan_start(local);
 
-		ieee80211_configure_filter(local); /* accept probe-responses */
+		ieee80211_configure_filter(sdata); /* accept probe-responses */
 
 		/* We need to ensure power level is at max for scanning. */
 		ieee80211_hw_config(local, 0);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1df4019..74aab81 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1193,9 +1193,6 @@ void ieee80211_stop_device(struct ieee80211_local *local)
 {
 	ieee80211_led_radio(local, false);
 	ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
-
-	cancel_work_sync(&local->reconfig_filter);
-
 	flush_workqueue(local->workqueue);
 	drv_stop(local);
 }
@@ -1312,7 +1309,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	/* reconfigure hardware */
 	ieee80211_hw_config(local, ~0);
 
-	ieee80211_configure_filter(local);
+	list_for_each_entry(sdata, &local->interfaces, list)
+		ieee80211_configure_filter(sdata);
 
 	/* Finally also reconfigure all the BSS information */
 	list_for_each_entry(sdata, &local->interfaces, list) {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux Kernel]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Photo]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]     [Free Dating]     [M2M Wireless]

Add to Google Powered by Linux