diff options
| author | Mark Brown <broonie@kernel.org> | 2024-04-09 23:27:14 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2024-04-09 23:27:14 +0100 |
| commit | 8a8317f92770ab70ff39b15de74bdb3a07fdb6cb (patch) | |
| tree | ce65ca0b98c15e7358925ecba5273eefb1b50256 /kernel/time/timer_migration.c | |
| parent | aad6b35290f52639d3601063d33d9621c0948a04 (diff) | |
| parent | f63eb9ae085dc6da27eebfe35317e07a6a02a160 (diff) | |
regmap: kunit: Add some test cases and a few small
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:
This series adds some more test cases, mainly for testing:
commit eaa03486d932 ("regmap: maple: Fix uninitialized symbol 'ret' warnings")
commit 00bb549d7d63 ("regmap: maple: Fix cache corruption in regcache_maple_drop()")
And the pending patch ("regmap: Add regmap_read_bypassed()")
There are also a few small improvements to the KUnit implementation.
Diffstat (limited to 'kernel/time/timer_migration.c')
| -rw-r--r-- | kernel/time/timer_migration.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/kernel/time/timer_migration.c b/kernel/time/timer_migration.c index c63a0afdcebe..ccba875d2234 100644 --- a/kernel/time/timer_migration.c +++ b/kernel/time/timer_migration.c @@ -751,6 +751,33 @@ bool tmigr_update_events(struct tmigr_group *group, struct tmigr_group *child, first_childevt = evt = data->evt; + /* + * Walking the hierarchy is required in any case when a + * remote expiry was done before. This ensures to not lose + * already queued events in non active groups (see section + * "Required event and timerqueue update after a remote + * expiry" in the documentation at the top). + * + * The two call sites which are executed without a remote expiry + * before, are not prevented from propagating changes through + * the hierarchy by the return: + * - When entering this path by tmigr_new_timer(), @evt->ignore + * is never set. + * - tmigr_inactive_up() takes care of the propagation by + * itself and ignores the return value. But an immediate + * return is possible if there is a parent, sparing group + * locking at this level, because the upper walking call to + * the parent will take care about removing this event from + * within the group and update next_expiry accordingly. + * + * However if there is no parent, ie: the hierarchy has only a + * single level so @group is the top level group, make sure the + * first event information of the group is updated properly and + * also handled properly, so skip this fast return path. + */ + if (evt->ignore && !remote && group->parent) + return true; + raw_spin_lock(&group->lock); childstate.state = 0; @@ -762,8 +789,11 @@ bool tmigr_update_events(struct tmigr_group *group, struct tmigr_group *child, * queue when the expiry time changed only or when it could be ignored. */ if (timerqueue_node_queued(&evt->nextevt)) { - if ((evt->nextevt.expires == nextexp) && !evt->ignore) + if ((evt->nextevt.expires == nextexp) && !evt->ignore) { + /* Make sure not to miss a new CPU event with the same expiry */ + evt->cpu = first_childevt->cpu; goto check_toplvl; + } if (!timerqueue_del(&group->events, &evt->nextevt)) WRITE_ONCE(group->next_expiry, KTIME_MAX); |
