3.16.52-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 9984d1b5835ca29fc7025186a891ee7398d21cc7 upstream.
In order to make the open/close more robust, widen the register_mutex protection over the whole snd_timer_close() function. Also, the close procedure is slightly shuffled to be in the safer order, as well as a few code refactoring.
Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Ben Hutchings ben@decadent.org.uk --- sound/core/timer.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-)
--- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -334,25 +334,14 @@ int snd_timer_close(struct snd_timer_ins if (snd_BUG_ON(!timeri)) return -ENXIO;
+ mutex_lock(®ister_mutex); + list_del(&timeri->open_list); + /* force to stop the timer */ snd_timer_stop(timeri);
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - /* wait, until the active callback is finished */ - spin_lock_irq(&slave_active_lock); - while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { - spin_unlock_irq(&slave_active_lock); - udelay(10); - spin_lock_irq(&slave_active_lock); - } - spin_unlock_irq(&slave_active_lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - mutex_unlock(®ister_mutex); - } else { - timer = timeri->timer; - if (snd_BUG_ON(!timer)) - goto out; + timer = timeri->timer; + if (timer) { /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { @@ -361,11 +350,7 @@ int snd_timer_close(struct snd_timer_ins spin_lock_irq(&timer->lock); } spin_unlock_irq(&timer->lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - if (list_empty(&timer->open_list_head) && - timer->hw.close) - timer->hw.close(timer); + /* remove slave links */ spin_lock_irq(&slave_active_lock); spin_lock(&timer->lock); @@ -379,18 +364,27 @@ int snd_timer_close(struct snd_timer_ins } spin_unlock(&timer->lock); spin_unlock_irq(&slave_active_lock); - /* release a card refcount for safe disconnection */ - if (timer->card) - put_device(&timer->card->card_dev); - mutex_unlock(®ister_mutex); + + /* slave doesn't need to release timer resources below */ + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + timer = NULL; } - out: + if (timeri->private_free) timeri->private_free(timeri); kfree(timeri->owner); kfree(timeri); - if (timer) + + if (timer) { + if (list_empty(&timer->open_list_head) && timer->hw.close) + timer->hw.close(timer); + /* release a card refcount for safe disconnection */ + if (timer->card) + put_device(&timer->card->card_dev); module_put(timer->module); + } + + mutex_unlock(®ister_mutex); return 0; }