summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-06-24 10:57:41 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:15 +0200
commitb2e8434f1829bb500f79b1adb80ffed2316811cf (patch)
tree841792c5012652e81cd60f5d6e158f59564365d9 /net/mac80211/mlme.c
parent94ddc3b5aa21c261be277eab8bc80f7520038a34 (diff)
downloadlinux-b2e8434f1829bb500f79b1adb80ffed2316811cf.tar.bz2
wifi: mac80211: set up/tear down client vif links properly
In station/client mode, the link data needs a bit more initialization and destruction than just zero-init and kfree() respectively, implement that. This required some shuffling of the link data handling in general, as we should set it up in setup and do the teardown in teardown, otherwise we're asymmetric in case of interface type changes. Also stop using kfree_rcu(), we cannot guarantee that nothing is scheduling things that live within the link (e.g. the u.mgd.request_smps_work) until we're sure it cannot be referenced anymore, therefore synchronize instead. This isn't very efficient, but we can always optimize it later. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d4d226436e8d..299381d19760 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -5033,17 +5033,14 @@ static void ieee80211_request_smps_mgd_work(struct work_struct *work)
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_if_managed *ifmgd;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- ifmgd = &sdata->u.mgd;
INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
INIT_WORK(&ifmgd->beacon_connection_loss_work,
ieee80211_beacon_connection_loss_work);
INIT_WORK(&ifmgd->csa_connection_drop_work,
ieee80211_csa_connection_drop_work);
- INIT_WORK(&sdata->deflink.u.mgd.request_smps_work,
- ieee80211_request_smps_mgd_work);
INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
ieee80211_tdls_peer_del_work);
timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0);
@@ -5057,20 +5054,28 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->powersave = sdata->wdev.ps;
ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
- sdata->deflink.u.mgd.p2p_noa_index = -1;
- sdata->deflink.u.mgd.conn_flags = 0;
-
- if (sdata->local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS)
- sdata->deflink.u.mgd.req_smps = IEEE80211_SMPS_AUTOMATIC;
- else
- sdata->deflink.u.mgd.req_smps = IEEE80211_SMPS_OFF;
-
/* Setup TDLS data */
spin_lock_init(&ifmgd->teardown_lock);
ifmgd->teardown_skb = NULL;
ifmgd->orig_teardown_skb = NULL;
}
+void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
+{
+ struct ieee80211_local *local = link->sdata->local;
+
+ link->u.mgd.p2p_noa_index = -1;
+ link->u.mgd.conn_flags = 0;
+ link->conf->bssid = link->u.mgd.bssid;
+
+ INIT_WORK(&link->u.mgd.request_smps_work,
+ ieee80211_request_smps_mgd_work);
+ if (local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS)
+ link->u.mgd.req_smps = IEEE80211_SMPS_AUTOMATIC;
+ else
+ link->u.mgd.req_smps = IEEE80211_SMPS_OFF;
+}
+
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
{
@@ -6383,6 +6388,11 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
return 0;
}
+void ieee80211_mgd_stop_link(struct ieee80211_link_data *link)
+{
+ cancel_work_sync(&link->u.mgd.request_smps_work);
+}
+
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -6394,7 +6404,6 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
*/
cancel_work_sync(&ifmgd->monitor_work);
cancel_work_sync(&ifmgd->beacon_connection_loss_work);
- cancel_work_sync(&sdata->deflink.u.mgd.request_smps_work);
cancel_work_sync(&ifmgd->csa_connection_drop_work);
cancel_work_sync(&ifmgd->chswitch_work);
cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);