mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
ALSA: timer: Revert active callback sync check at close
This is essentially a revert of the commita7588c896b
("ALSA: timer: Check ack_list emptiness instead of bit flag"). The intended change by the commit turns out to be insufficient, as snd_timer_close*() always calls snd_timer_stop() that deletes the ack_list beforehand. In theory, we can change the behavior of snd_timer_stop() to sync the pending ack_list, but this will become a deadlock for the callback like sequencer that calls again snd_timer_stop() from itself. So, reverting the change is a more straightforward solution. Fixes:a7588c896b
("ALSA: timer: Check ack_list emptiness instead of bit flag") Reported-by: syzbot+58813d77154713f4de15@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
4b81dad109
commit
df55531b8b
@ -43,6 +43,7 @@
|
||||
#define SNDRV_TIMER_IFLG_START 0x00000004
|
||||
#define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */
|
||||
#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use tasklet) */
|
||||
#define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */
|
||||
#define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */
|
||||
#define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */
|
||||
|
||||
|
@ -372,7 +372,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
|
||||
timer->num_instances--;
|
||||
/* wait, until the active callback is finished */
|
||||
spin_lock_irq(&timer->lock);
|
||||
while (!list_empty(&timeri->ack_list)) {
|
||||
while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
|
||||
spin_unlock_irq(&timer->lock);
|
||||
udelay(10);
|
||||
spin_lock_irq(&timer->lock);
|
||||
@ -748,19 +748,20 @@ static void snd_timer_process_callbacks(struct snd_timer *timer,
|
||||
ti = list_first_entry(head, struct snd_timer_instance,
|
||||
ack_list);
|
||||
|
||||
/* remove from ack_list and make empty */
|
||||
list_del_init(&ti->ack_list);
|
||||
|
||||
if (!(ti->flags & SNDRV_TIMER_IFLG_DEAD)) {
|
||||
ticks = ti->pticks;
|
||||
ti->pticks = 0;
|
||||
resolution = ti->resolution;
|
||||
|
||||
ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
|
||||
spin_unlock(&timer->lock);
|
||||
if (ti->callback)
|
||||
ti->callback(ti, resolution, ticks);
|
||||
spin_lock(&timer->lock);
|
||||
ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
|
||||
}
|
||||
|
||||
/* remove from ack_list and make empty */
|
||||
list_del_init(&ti->ack_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user