summaryrefslogtreecommitdiff
path: root/sound/core/timer.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-07-23 14:04:37 -0700
committerJakub Kicinski <kuba@kernel.org>2026-07-23 14:07:40 -0700
commit89d8006259b81dd25c962f6cc8d7ab268d6ea426 (patch)
tree6fb362a45540a3531072b20907d19e11e8f8b7b3 /sound/core/timer.c
parented6dc972c19ff9ffca504f5739848da4275219e3 (diff)
parentd326f83e819c53aa05c40d64f5805d6237b6aa1b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.2-rc5). Conflicts: drivers/net/amt.c 3656a79f94c47 ("amt: re-read skb header pointers after every pull") 586c4dcf28eb6 ("amt: no longer rely on RTNL in amt_fill_info()") https://lore.kernel.org/amIaJr3aOQNS_Fvl@sirena.org.uk Adjacent changes: drivers/net/geneve.c 8efb8f8bbb35 ("geneve: require CAP_NET_ADMIN in the device netns for changelink") 0ba269933f73 ("geneve: convert config to RCU-protected pointer") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r--sound/core/timer.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 51c6ac4df9f4..07ef127b29e1 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -489,10 +489,20 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
snd_timer_stop(timeri);
if (timer) {
+ struct snd_timer_instance *slave;
+ bool busy;
+
timer->num_instances--;
- /* wait, until the active callback is finished */
+ /* unqueue then drain the slaves' callbacks before remove_slave_links() severs them */
spin_lock_irq(&timer->lock);
- while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
+ list_for_each_entry(slave, &timeri->slave_list_head, open_list)
+ list_del_init(&slave->ack_list);
+ for (;;) {
+ busy = timeri->flags & SNDRV_TIMER_IFLG_CALLBACK;
+ list_for_each_entry(slave, &timeri->slave_list_head, open_list)
+ busy |= slave->flags & SNDRV_TIMER_IFLG_CALLBACK;
+ if (!busy)
+ break;
spin_unlock_irq(&timer->lock);
udelay(10);
spin_lock_irq(&timer->lock);
@@ -927,12 +937,15 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
ack_list_head = &timer->ack_list_head;
else
ack_list_head = &timer->sack_list_head;
- if (list_empty(&ti->ack_list))
+ /* don't requeue an instance whose callback is still running */
+ if (list_empty(&ti->ack_list) &&
+ !(ti->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ti->ack_list, ack_list_head);
list_for_each_entry(ts, &ti->slave_active_head, active_list) {
ts->pticks = ti->pticks;
ts->resolution = resolution;
- if (list_empty(&ts->ack_list))
+ if (list_empty(&ts->ack_list) &&
+ !(ts->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ts->ack_list, ack_list_head);
}
}