From: Ben Greear Re-initialization could cause corruption in work queues in case links were not properly stopped for some reason. Signed-off-by: Ben Greear --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/link.c | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d71e0c6d2165..ac4e10f16cd9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1079,6 +1079,7 @@ struct ieee80211_link_data { bool operating_11g_mode; + bool already_initialized; /* has ieee80211_link_init been called? */ struct { struct wiphy_work finalize_work; diff --git a/net/mac80211/link.c b/net/mac80211/link.c index 03bfca27d205..6125e79f67c9 100644 --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -110,14 +110,25 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, link->user_power_level = sdata->local->user_power_level; link_conf->txpower = INT_MIN; - wiphy_work_init(&link->csa.finalize_work, - ieee80211_csa_finalize_work); - wiphy_work_init(&link->color_change_finalize_work, - ieee80211_color_change_finalize_work); - wiphy_delayed_work_init(&link->color_collision_detect_work, - ieee80211_color_collision_detection_work); - wiphy_hrtimer_work_init(&link->dfs_cac_timer_work, - ieee80211_dfs_cac_timer_work); + if (link->already_initialized) { + wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy, + &link->color_collision_detect_work); + wiphy_work_cancel(link->sdata->local->hw.wiphy, + &link->color_change_finalize_work); + wiphy_work_cancel(link->sdata->local->hw.wiphy, + &link->csa.finalize_work); + wiphy_hrtimer_work_cancel(link->sdata->local->hw.wiphy, + &link->dfs_cac_timer_work); + } else { + wiphy_work_init(&link->csa.finalize_work, + ieee80211_csa_finalize_work); + wiphy_work_init(&link->color_change_finalize_work, + ieee80211_color_change_finalize_work); + wiphy_delayed_work_init(&link->color_collision_detect_work, + ieee80211_color_collision_detection_work); + wiphy_hrtimer_work_init(&link->dfs_cac_timer_work, + ieee80211_dfs_cac_timer_work); + } if (!deflink) { switch (sdata->vif.type) { @@ -138,6 +149,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, ieee80211_link_debugfs_add(link); } + link->already_initialized = true; rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf); rcu_assign_pointer(sdata->link[link_id], link); } -- 2.42.0