Skip to content

Commit 56cfb8c

Browse files
committed
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>
1 parent 7483a21 commit 56cfb8c

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

include/net/cfg80211.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5826,6 +5826,16 @@ void wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *work);
58265826
*/
58275827
void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work);
58285828

5829+
/**
5830+
* wiphy_work_flush - flush previously queued work
5831+
* @wiphy: the wiphy, for debug purposes
5832+
* @work: the work to flush, this can be %NULL to flush all work
5833+
*
5834+
* Flush the work (i.e. run it if pending). This must be called
5835+
* under the wiphy mutex acquired by wiphy_lock().
5836+
*/
5837+
void wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *work);
5838+
58295839
struct wiphy_delayed_work {
58305840
struct wiphy_work work;
58315841
struct wiphy *wiphy;
@@ -5869,6 +5879,17 @@ void wiphy_delayed_work_queue(struct wiphy *wiphy,
58695879
void wiphy_delayed_work_cancel(struct wiphy *wiphy,
58705880
struct wiphy_delayed_work *dwork);
58715881

5882+
/**
5883+
* wiphy_delayed work_flush - flush previously queued delayed work
5884+
* @wiphy: the wiphy, for debug purposes
5885+
* @work: the work to flush
5886+
*
5887+
* Flush the work (i.e. run it if pending). This must be called
5888+
* under the wiphy mutex acquired by wiphy_lock().
5889+
*/
5890+
void wiphy_delayed_work_flush(struct wiphy *wiphy,
5891+
struct wiphy_delayed_work *dwork);
5892+
58725893
/**
58735894
* struct wireless_dev - wireless device state
58745895
*

net/wireless/core.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,8 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy)
10491049
}
10501050
EXPORT_SYMBOL(wiphy_rfkill_start_polling);
10511051

1052-
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev)
1052+
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
1053+
struct wiphy_work *end)
10531054
{
10541055
unsigned int runaway_limit = 100;
10551056
unsigned long flags;
@@ -1068,6 +1069,10 @@ void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev)
10681069
wk->func(&rdev->wiphy, wk);
10691070

10701071
spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
1072+
1073+
if (wk == end)
1074+
break;
1075+
10711076
if (WARN_ON(--runaway_limit == 0))
10721077
INIT_LIST_HEAD(&rdev->wiphy_work_list);
10731078
}
@@ -1118,7 +1123,7 @@ void wiphy_unregister(struct wiphy *wiphy)
11181123
#endif
11191124

11201125
/* surely nothing is reachable now, clean up work */
1121-
cfg80211_process_wiphy_works(rdev);
1126+
cfg80211_process_wiphy_works(rdev, NULL);
11221127
wiphy_unlock(&rdev->wiphy);
11231128
rtnl_unlock();
11241129

@@ -1640,6 +1645,21 @@ void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work)
16401645
}
16411646
EXPORT_SYMBOL_GPL(wiphy_work_cancel);
16421647

1648+
void wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *work)
1649+
{
1650+
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1651+
unsigned long flags;
1652+
bool run;
1653+
1654+
spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
1655+
run = !work || !list_empty(&work->entry);
1656+
spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags);
1657+
1658+
if (run)
1659+
cfg80211_process_wiphy_works(rdev, work);
1660+
}
1661+
EXPORT_SYMBOL_GPL(wiphy_work_flush);
1662+
16431663
void wiphy_delayed_work_timer(struct timer_list *t)
16441664
{
16451665
struct wiphy_delayed_work *dwork = from_timer(dwork, t, timer);
@@ -1672,6 +1692,16 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy,
16721692
}
16731693
EXPORT_SYMBOL_GPL(wiphy_delayed_work_cancel);
16741694

1695+
void wiphy_delayed_work_flush(struct wiphy *wiphy,
1696+
struct wiphy_delayed_work *dwork)
1697+
{
1698+
lockdep_assert_held(&wiphy->mtx);
1699+
1700+
del_timer_sync(&dwork->timer);
1701+
wiphy_work_flush(wiphy, &dwork->work);
1702+
}
1703+
EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush);
1704+
16751705
static int __init cfg80211_init(void)
16761706
{
16771707
int err;

net/wireless/core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
469469
struct net_device *dev, enum nl80211_iftype ntype,
470470
struct vif_params *params);
471471
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
472-
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev);
472+
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
473+
struct wiphy_work *end);
473474
void cfg80211_process_wdev_events(struct wireless_dev *wdev);
474475

475476
bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,

net/wireless/sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,14 @@ static int wiphy_suspend(struct device *dev)
105105
cfg80211_leave_all(rdev);
106106
cfg80211_process_rdev_events(rdev);
107107
}
108-
cfg80211_process_wiphy_works(rdev);
108+
cfg80211_process_wiphy_works(rdev, NULL);
109109
if (rdev->ops->suspend)
110110
ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
111111
if (ret == 1) {
112112
/* Driver refuse to configure wowlan */
113113
cfg80211_leave_all(rdev);
114114
cfg80211_process_rdev_events(rdev);
115-
cfg80211_process_wiphy_works(rdev);
115+
cfg80211_process_wiphy_works(rdev, NULL);
116116
ret = rdev_suspend(rdev, NULL);
117117
}
118118
if (ret == 0)

0 commit comments

Comments
 (0)