Commit b71d856a authored by Benjamin Beichler's avatar Benjamin Beichler Committed by Johannes Berg

mac80211_hwsim: add workqueue to wait for deferred radio deletion on mod unload

When closing multiple wmediumd instances with many radios and try to
unload the  mac80211_hwsim module, it may happen that the work items live
longer than the module. To wait especially for this deletion work items,
add a work queue, otherwise flush_scheduled_work would be necessary.
Signed-off-by: default avatarBenjamin Beichler <benjamin.beichler@uni-rostock.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7a94b8c2
...@@ -489,6 +489,7 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { ...@@ -489,6 +489,7 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
static spinlock_t hwsim_radio_lock; static spinlock_t hwsim_radio_lock;
static LIST_HEAD(hwsim_radios); static LIST_HEAD(hwsim_radios);
static struct workqueue_struct *hwsim_wq;
static int hwsim_radio_idx; static int hwsim_radio_idx;
static struct platform_driver mac80211_hwsim_driver = { static struct platform_driver mac80211_hwsim_driver = {
...@@ -3342,7 +3343,7 @@ static void remove_user_radios(u32 portid) ...@@ -3342,7 +3343,7 @@ static void remove_user_radios(u32 portid)
if (entry->destroy_on_close && entry->portid == portid) { if (entry->destroy_on_close && entry->portid == portid) {
list_del(&entry->list); list_del(&entry->list);
INIT_WORK(&entry->destroy_work, destroy_radio); INIT_WORK(&entry->destroy_work, destroy_radio);
schedule_work(&entry->destroy_work); queue_work(hwsim_wq, &entry->destroy_work);
} }
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
...@@ -3417,7 +3418,7 @@ static void __net_exit hwsim_exit_net(struct net *net) ...@@ -3417,7 +3418,7 @@ static void __net_exit hwsim_exit_net(struct net *net)
list_del(&data->list); list_del(&data->list);
INIT_WORK(&data->destroy_work, destroy_radio); INIT_WORK(&data->destroy_work, destroy_radio);
schedule_work(&data->destroy_work); queue_work(hwsim_wq, &data->destroy_work);
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
} }
...@@ -3449,6 +3450,10 @@ static int __init init_mac80211_hwsim(void) ...@@ -3449,6 +3450,10 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init(&hwsim_radio_lock); spin_lock_init(&hwsim_radio_lock);
hwsim_wq = alloc_workqueue("hwsim_wq",WQ_MEM_RECLAIM,0);
if (!hwsim_wq)
return -ENOMEM;
err = register_pernet_device(&hwsim_net_ops); err = register_pernet_device(&hwsim_net_ops);
if (err) if (err)
return err; return err;
...@@ -3587,8 +3592,11 @@ static void __exit exit_mac80211_hwsim(void) ...@@ -3587,8 +3592,11 @@ static void __exit exit_mac80211_hwsim(void)
hwsim_exit_netlink(); hwsim_exit_netlink();
mac80211_hwsim_free(); mac80211_hwsim_free();
flush_workqueue(hwsim_wq);
unregister_netdev(hwsim_mon); unregister_netdev(hwsim_mon);
platform_driver_unregister(&mac80211_hwsim_driver); platform_driver_unregister(&mac80211_hwsim_driver);
unregister_pernet_device(&hwsim_net_ops); unregister_pernet_device(&hwsim_net_ops);
destroy_workqueue(hwsim_wq);
} }
module_exit(exit_mac80211_hwsim); module_exit(exit_mac80211_hwsim);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment