wifi: cfg80211: add flush functions for wiphy work

There may be sometimes reasons to actually run the work
if it's pending, add flush functions for both regular and
delayed wiphy work that will do this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2023-08-28 13:59:33 +02:00
parent 7483a2147a
commit 56cfb8ce1f
4 changed files with 57 additions and 5 deletions

View file

@ -5826,6 +5826,16 @@ void wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *work);
*/
void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work);
/**
* wiphy_work_flush - flush previously queued work
* @wiphy: the wiphy, for debug purposes
* @work: the work to flush, this can be %NULL to flush all work
*
* Flush the work (i.e. run it if pending). This must be called
* under the wiphy mutex acquired by wiphy_lock().
*/
void wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *work);
struct wiphy_delayed_work {
struct wiphy_work work;
struct wiphy *wiphy;
@ -5869,6 +5879,17 @@ void wiphy_delayed_work_queue(struct wiphy *wiphy,
void wiphy_delayed_work_cancel(struct wiphy *wiphy,
struct wiphy_delayed_work *dwork);
/**
* wiphy_delayed work_flush - flush previously queued delayed work
* @wiphy: the wiphy, for debug purposes
* @work: the work to flush
*
* Flush the work (i.e. run it if pending). This must be called
* under the wiphy mutex acquired by wiphy_lock().
*/
void wiphy_delayed_work_flush(struct wiphy *wiphy,
struct wiphy_delayed_work *dwork);
/**
* struct wireless_dev - wireless device state
*

View file

@ -1049,7 +1049,8 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy)
}
EXPORT_SYMBOL(wiphy_rfkill_start_polling);
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev)
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
struct wiphy_work *end)
{
unsigned int runaway_limit = 100;
unsigned long flags;
@ -1068,6 +1069,10 @@ void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev)
wk->func(&rdev->wiphy, wk);
spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
if (wk == end)
break;
if (WARN_ON(--runaway_limit == 0))
INIT_LIST_HEAD(&rdev->wiphy_work_list);
}
@ -1118,7 +1123,7 @@ void wiphy_unregister(struct wiphy *wiphy)
#endif
/* surely nothing is reachable now, clean up work */
cfg80211_process_wiphy_works(rdev);
cfg80211_process_wiphy_works(rdev, NULL);
wiphy_unlock(&rdev->wiphy);
rtnl_unlock();
@ -1640,6 +1645,21 @@ void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work)
}
EXPORT_SYMBOL_GPL(wiphy_work_cancel);
void wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *work)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
unsigned long flags;
bool run;
spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
run = !work || !list_empty(&work->entry);
spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags);
if (run)
cfg80211_process_wiphy_works(rdev, work);
}
EXPORT_SYMBOL_GPL(wiphy_work_flush);
void wiphy_delayed_work_timer(struct timer_list *t)
{
struct wiphy_delayed_work *dwork = from_timer(dwork, t, timer);
@ -1672,6 +1692,16 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy,
}
EXPORT_SYMBOL_GPL(wiphy_delayed_work_cancel);
void wiphy_delayed_work_flush(struct wiphy *wiphy,
struct wiphy_delayed_work *dwork)
{
lockdep_assert_held(&wiphy->mtx);
del_timer_sync(&dwork->timer);
wiphy_work_flush(wiphy, &dwork->work);
}
EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush);
static int __init cfg80211_init(void)
{
int err;

View file

@ -469,7 +469,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
struct net_device *dev, enum nl80211_iftype ntype,
struct vif_params *params);
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev);
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
struct wiphy_work *end);
void cfg80211_process_wdev_events(struct wireless_dev *wdev);
bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,

View file

@ -105,14 +105,14 @@ static int wiphy_suspend(struct device *dev)
cfg80211_leave_all(rdev);
cfg80211_process_rdev_events(rdev);
}
cfg80211_process_wiphy_works(rdev);
cfg80211_process_wiphy_works(rdev, NULL);
if (rdev->ops->suspend)
ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
if (ret == 1) {
/* Driver refuse to configure wowlan */
cfg80211_leave_all(rdev);
cfg80211_process_rdev_events(rdev);
cfg80211_process_wiphy_works(rdev);
cfg80211_process_wiphy_works(rdev, NULL);
ret = rdev_suspend(rdev, NULL);
}
if (ret == 0)