Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d34ba216 authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: don't delay station destruction



If we can assume that stations are never referenced by the
driver after sta_state returns (and this is true since the
previous iwlmvm patch and for all other drivers) then we
don't need to delay station destruction, and don't need to
play tricks with rcu_barrier() etc.

This should speed up some scenarios like hostapd shutdown.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a710c816
Loading
Loading
Loading
Loading
+3 −7
Original line number Diff line number Diff line
@@ -1098,15 +1098,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
		kfree_rcu(old_probe_resp, rcu_head);

	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
		sta_info_flush_defer(vlan);
	sta_info_flush_defer(sdata);
		sta_info_flush(vlan);
	sta_info_flush(sdata);
	synchronize_net();
	rcu_barrier();
	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
		sta_info_flush_cleanup(vlan);
	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
		ieee80211_free_keys(vlan);
	}
	sta_info_flush_cleanup(sdata);
	ieee80211_free_keys(sdata);

	sdata->vif.bss_conf.enable_beacon = false;
+0 −4
Original line number Diff line number Diff line
@@ -776,10 +776,6 @@ struct ieee80211_sub_if_data {
		u32 mntr_flags;
	} u;

	spinlock_t cleanup_stations_lock;
	struct list_head cleanup_stations;
	struct work_struct cleanup_stations_wk;

#ifdef CONFIG_MAC80211_DEBUGFS
	struct {
		struct dentry *subdir_stations;
+4 −23
Original line number Diff line number Diff line
@@ -786,10 +786,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
	 * This is relevant only in WDS mode, in all other modes we've
	 * already removed all stations when disconnecting or similar,
	 * so warn otherwise.
	 *
	 * We call sta_info_flush_cleanup() later, to combine RCU waits.
	 */
	flushed = sta_info_flush_defer(sdata);
	flushed = sta_info_flush(sdata);
	WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
		     (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));

@@ -892,16 +890,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
		/*
		 * When we get here, the interface is marked down.
		 *
		 * sta_info_flush_cleanup() requires rcu_barrier()
		 * first to wait for the station call_rcu() calls
		 * to complete, and we also need synchronize_rcu()
		 * to wait for the RX path in case it is using the
		 * interface and enqueuing frames at this very time on
		 * another CPU.
		 * We need synchronize_rcu() to wait for the RX path in
		 * case it is using the interface and enqueuing frames
		 * at this very time on another CPU.
		 */
		synchronize_rcu();
		rcu_barrier();
		sta_info_flush_cleanup(sdata);

		/*
		 * Free all remaining keys, there shouldn't be any,
@@ -1568,15 +1561,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
	mutex_unlock(&local->iflist_mtx);
}

static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);

	ieee80211_cleanup_sdata_stas(sdata);
}

int ieee80211_if_add(struct ieee80211_local *local, const char *name,
		     struct wireless_dev **new_wdev, enum nl80211_iftype type,
		     struct vif_params *params)
@@ -1649,9 +1633,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

	INIT_LIST_HEAD(&sdata->key_list);

	spin_lock_init(&sdata->cleanup_stations_lock);
	INIT_LIST_HEAD(&sdata->cleanup_stations);
	INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
	INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
			  ieee80211_dfs_cac_timer_work);
	INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
+1 −1
Original line number Diff line number Diff line
@@ -1698,7 +1698,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
	memset(ifmgd->bssid, 0, ETH_ALEN);

	/* remove AP and TDLS peers */
	sta_info_flush_defer(sdata);
	sta_info_flush(sdata);

	/* finally reset all BSS / config parameters */
	changed |= ieee80211_reset_erp_info(sdata);
+1 −2
Original line number Diff line number Diff line
@@ -37,9 +37,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
					IEEE80211_MAX_QUEUE_MAP,
					IEEE80211_QUEUE_STOP_REASON_SUSPEND);

	/* flush out all packets and station cleanup call_rcu()s */
	/* flush out all packets */
	synchronize_net();
	rcu_barrier();

	ieee80211_flush_queues(local, NULL);

Loading