mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 21:35:07 +00:00
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:
parent
7483a2147a
commit
56cfb8ce1f
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user