Commit 68d0021f authored by Remi Pommarel's avatar Remi Pommarel Committed by Johannes Berg
Browse files

wifi: cfg80211: Add wiphy_delayed_work_pending()



Add wiphy_delayed_work_pending() to check if any delayed work timer is
pending, that can be used to be sure that wiphy_delayed_work_queue()
won't postpone an already pending delayed work.

Signed-off-by: default avatarRemi Pommarel <repk@triplefau.lt>
Link: https://patch.msgid.link/20240924192805.13859-2-repk@triplefau.lt


[fix return value kernel-doc]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e1a9ae3a
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -6129,6 +6129,50 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy,
void wiphy_delayed_work_flush(struct wiphy *wiphy,
			      struct wiphy_delayed_work *dwork);

/**
 * wiphy_delayed_work_pending - Find out whether a wiphy delayable
 * work item is currently pending.
 *
 * @wiphy: the wiphy, for debug purposes
 * @dwork: the delayed work in question
 *
 * Return: true if timer is pending, false otherwise
 *
 * How wiphy_delayed_work_queue() works is by setting a timer which
 * when it expires calls wiphy_work_queue() to queue the wiphy work.
 * Because wiphy_delayed_work_queue() uses mod_timer(), if it is
 * called twice and the second call happens before the first call
 * deadline, the work will rescheduled for the second deadline and
 * won't run before that.
 *
 * wiphy_delayed_work_pending() can be used to detect if calling
 * wiphy_work_delayed_work_queue() would start a new work schedule
 * or delayed a previous one. As seen below it cannot be used to
 * detect precisely if the work has finished to execute nor if it
 * is currently executing.
 *
 *      CPU0                                CPU1
 * wiphy_delayed_work_queue(wk)
 *  mod_timer(wk->timer)
 *                                     wiphy_delayed_work_pending(wk) -> true
 *
 * [...]
 * expire_timers(wk->timer)
 *  detach_timer(wk->timer)
 *                                     wiphy_delayed_work_pending(wk) -> false
 *  wk->timer->function()                          |
 *   wiphy_work_queue(wk)                          | delayed work pending
 *    list_add_tail()                              | returns false but
 *    queue_work(cfg80211_wiphy_work)              | wk->func() has not
 *                                                 | been run yet
 * [...]                                           |
 *  cfg80211_wiphy_work()                          |
 *   wk->func()                                    V
 *
 */
bool wiphy_delayed_work_pending(struct wiphy *wiphy,
				struct wiphy_delayed_work *dwork);

/**
 * enum ieee80211_ap_reg_power - regulatory power for an Access Point
 *
+7 −0
Original line number Diff line number Diff line
@@ -1704,6 +1704,13 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy,
}
EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush);

bool wiphy_delayed_work_pending(struct wiphy *wiphy,
				struct wiphy_delayed_work *dwork)
{
	return timer_pending(&dwork->timer);
}
EXPORT_SYMBOL_GPL(wiphy_delayed_work_pending);

static int __init cfg80211_init(void)
{
	int err;