--- /dev/null
+From 635f7ef2cc4ea7adc147380526ce75f4bfe9a8b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2019 22:42:57 +0100
+Subject: ALSA: timer: Fix mutex deadlock at releasing card
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit a39331867335d4a94b6165e306265c9e24aca073 ]
+
+When a card is disconnected while in use, the system waits until all
+opened files are closed then releases the card. This is done via
+put_device() of the card device in each device release code.
+
+The recently reported mutex deadlock bug happens in this code path;
+snd_timer_close() for the timer device deals with the global
+register_mutex and it calls put_device() there. When this timer
+device is the last one, the card gets freed and it eventually calls
+snd_timer_free(), which has again the protection with the global
+register_mutex -- boom.
+
+Basically put_device() call itself is race-free, so a relative simple
+workaround is to move this put_device() call out of the mutex. For
+achieving that, in this patch, snd_timer_close_locked() got a new
+argument to store the card device pointer in return, and each caller
+invokes put_device() with the returned object after the mutex unlock.
+
+Reported-and-tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/timer.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index 6eb4e97662d9c..19d90aa082184 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -239,7 +239,8 @@ static int snd_timer_check_master(struct snd_timer_instance *master)
+ return 0;
+ }
+
+-static int snd_timer_close_locked(struct snd_timer_instance *timeri);
++static int snd_timer_close_locked(struct snd_timer_instance *timeri,
++ struct device **card_devp_to_put);
+
+ /*
+ * open a timer instance
+@@ -251,6 +252,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ {
+ struct snd_timer *timer;
+ struct snd_timer_instance *timeri = NULL;
++ struct device *card_dev_to_put = NULL;
+ int err;
+
+ mutex_lock(®ister_mutex);
+@@ -274,7 +276,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ list_add_tail(&timeri->open_list, &snd_timer_slave_list);
+ err = snd_timer_check_slave(timeri);
+ if (err < 0) {
+- snd_timer_close_locked(timeri);
++ snd_timer_close_locked(timeri, &card_dev_to_put);
+ timeri = NULL;
+ }
+ goto unlock;
+@@ -326,7 +328,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ timeri = NULL;
+
+ if (timer->card)
+- put_device(&timer->card->card_dev);
++ card_dev_to_put = &timer->card->card_dev;
+ module_put(timer->module);
+ goto unlock;
+ }
+@@ -336,12 +338,15 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ timer->num_instances++;
+ err = snd_timer_check_master(timeri);
+ if (err < 0) {
+- snd_timer_close_locked(timeri);
++ snd_timer_close_locked(timeri, &card_dev_to_put);
+ timeri = NULL;
+ }
+
+ unlock:
+ mutex_unlock(®ister_mutex);
++ /* put_device() is called after unlock for avoiding deadlock */
++ if (card_dev_to_put)
++ put_device(card_dev_to_put);
+ *ti = timeri;
+ return err;
+ }
+@@ -351,7 +356,8 @@ EXPORT_SYMBOL(snd_timer_open);
+ * close a timer instance
+ * call this with register_mutex down.
+ */
+-static int snd_timer_close_locked(struct snd_timer_instance *timeri)
++static int snd_timer_close_locked(struct snd_timer_instance *timeri,
++ struct device **card_devp_to_put)
+ {
+ struct snd_timer *timer = NULL;
+ struct snd_timer_instance *slave, *tmp;
+@@ -403,7 +409,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
+ timer->hw.close(timer);
+ /* release a card refcount for safe disconnection */
+ if (timer->card)
+- put_device(&timer->card->card_dev);
++ *card_devp_to_put = &timer->card->card_dev;
+ module_put(timer->module);
+ }
+
+@@ -415,14 +421,18 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
+ */
+ int snd_timer_close(struct snd_timer_instance *timeri)
+ {
++ struct device *card_dev_to_put = NULL;
+ int err;
+
+ if (snd_BUG_ON(!timeri))
+ return -ENXIO;
+
+ mutex_lock(®ister_mutex);
+- err = snd_timer_close_locked(timeri);
++ err = snd_timer_close_locked(timeri, &card_dev_to_put);
+ mutex_unlock(®ister_mutex);
++ /* put_device() is called after unlock for avoiding deadlock */
++ if (card_dev_to_put)
++ put_device(card_dev_to_put);
+ return err;
+ }
+ EXPORT_SYMBOL(snd_timer_close);
+--
+2.20.1
+
--- /dev/null
+From 67272ec0784f5ee30b9c64022cf207b93995c46e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Jun 2017 16:16:05 +0200
+Subject: ALSA: timer: Follow standard EXPORT_SYMBOL() declarations
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 988563929d5b65c021439880ac6bd1b207722f26 ]
+
+Just a tidy up to follow the standard EXPORT_SYMBOL*() declarations
+in order to improve grep-ability.
+
+- Move EXPORT_SYMBOL*() to the position right after its definition
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/timer.c | 27 +++++++++++++--------------
+ 1 file changed, 13 insertions(+), 14 deletions(-)
+
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index 152254193c697..cfcc6718aafce 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -318,6 +318,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ *ti = timeri;
+ return 0;
+ }
++EXPORT_SYMBOL(snd_timer_open);
+
+ /*
+ * close a timer instance
+@@ -383,6 +384,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
+ mutex_unlock(®ister_mutex);
+ return 0;
+ }
++EXPORT_SYMBOL(snd_timer_close);
+
+ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
+ {
+@@ -397,6 +399,7 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
+ }
+ return 0;
+ }
++EXPORT_SYMBOL(snd_timer_resolution);
+
+ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
+ {
+@@ -588,6 +591,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
+ else
+ return snd_timer_start1(timeri, true, ticks);
+ }
++EXPORT_SYMBOL(snd_timer_start);
+
+ /*
+ * stop the timer instance.
+@@ -601,6 +605,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
+ else
+ return snd_timer_stop1(timeri, true);
+ }
++EXPORT_SYMBOL(snd_timer_stop);
+
+ /*
+ * start again.. the tick is kept.
+@@ -616,6 +621,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
+ else
+ return snd_timer_start1(timeri, false, 0);
+ }
++EXPORT_SYMBOL(snd_timer_continue);
+
+ /*
+ * pause.. remember the ticks left
+@@ -627,6 +633,7 @@ int snd_timer_pause(struct snd_timer_instance * timeri)
+ else
+ return snd_timer_stop1(timeri, false);
+ }
++EXPORT_SYMBOL(snd_timer_pause);
+
+ /*
+ * reschedule the timer
+@@ -808,6 +815,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
+ if (use_tasklet)
+ tasklet_schedule(&timer->task_queue);
+ }
++EXPORT_SYMBOL(snd_timer_interrupt);
+
+ /*
+
+@@ -858,6 +866,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
+ *rtimer = timer;
+ return 0;
+ }
++EXPORT_SYMBOL(snd_timer_new);
+
+ static int snd_timer_free(struct snd_timer *timer)
+ {
+@@ -977,6 +986,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
+ }
++EXPORT_SYMBOL(snd_timer_notify);
+
+ /*
+ * exported functions for global timers
+@@ -992,11 +1002,13 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
+ tid.subdevice = 0;
+ return snd_timer_new(NULL, id, &tid, rtimer);
+ }
++EXPORT_SYMBOL(snd_timer_global_new);
+
+ int snd_timer_global_free(struct snd_timer *timer)
+ {
+ return snd_timer_free(timer);
+ }
++EXPORT_SYMBOL(snd_timer_global_free);
+
+ int snd_timer_global_register(struct snd_timer *timer)
+ {
+@@ -1006,6 +1018,7 @@ int snd_timer_global_register(struct snd_timer *timer)
+ dev.device_data = timer;
+ return snd_timer_dev_register(&dev);
+ }
++EXPORT_SYMBOL(snd_timer_global_register);
+
+ /*
+ * System timer
+@@ -2121,17 +2134,3 @@ static void __exit alsa_timer_exit(void)
+
+ module_init(alsa_timer_init)
+ module_exit(alsa_timer_exit)
+-
+-EXPORT_SYMBOL(snd_timer_open);
+-EXPORT_SYMBOL(snd_timer_close);
+-EXPORT_SYMBOL(snd_timer_resolution);
+-EXPORT_SYMBOL(snd_timer_start);
+-EXPORT_SYMBOL(snd_timer_stop);
+-EXPORT_SYMBOL(snd_timer_continue);
+-EXPORT_SYMBOL(snd_timer_pause);
+-EXPORT_SYMBOL(snd_timer_new);
+-EXPORT_SYMBOL(snd_timer_notify);
+-EXPORT_SYMBOL(snd_timer_global_new);
+-EXPORT_SYMBOL(snd_timer_global_free);
+-EXPORT_SYMBOL(snd_timer_global_register);
+-EXPORT_SYMBOL(snd_timer_interrupt);
+--
+2.20.1
+
--- /dev/null
+From 5da6a4bd1d2a53d4ffd0ef9edc675a26382955c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Nov 2017 10:07:43 +0100
+Subject: ALSA: timer: Limit max instances per timer
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 9b7d869ee5a77ed4a462372bb89af622e705bfb8 ]
+
+Currently we allow unlimited number of timer instances, and it may
+bring the system hogging way too much CPU when too many timer
+instances are opened and processed concurrently. This may end up with
+a soft-lockup report as triggered by syzkaller, especially when
+hrtimer backend is deployed.
+
+Since such insane number of instances aren't demanded by the normal
+use case of ALSA sequencer and it merely opens a risk only for abuse,
+this patch introduces the upper limit for the number of instances per
+timer backend. As default, it's set to 1000, but for the fine-grained
+timer like hrtimer, it's set to 100.
+
+Reported-by: syzbot
+Tested-by: Jérôme Glisse <jglisse@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/sound/timer.h | 2 ++
+ sound/core/hrtimer.c | 1 +
+ sound/core/timer.c | 67 ++++++++++++++++++++++++++++++++++---------
+ 3 files changed, 57 insertions(+), 13 deletions(-)
+
+diff --git a/include/sound/timer.h b/include/sound/timer.h
+index c4d76ff056c6e..7ae226ab69908 100644
+--- a/include/sound/timer.h
++++ b/include/sound/timer.h
+@@ -90,6 +90,8 @@ struct snd_timer {
+ struct list_head ack_list_head;
+ struct list_head sack_list_head; /* slow ack list head */
+ struct tasklet_struct task_queue;
++ int max_instances; /* upper limit of timer instances */
++ int num_instances; /* current number of timer instances */
+ };
+
+ struct snd_timer_instance {
+diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
+index e2f27022b363c..d7dddb75e7bb8 100644
+--- a/sound/core/hrtimer.c
++++ b/sound/core/hrtimer.c
+@@ -159,6 +159,7 @@ static int __init snd_hrtimer_init(void)
+ timer->hw = hrtimer_hw;
+ timer->hw.resolution = resolution;
+ timer->hw.ticks = NANO_SEC / resolution;
++ timer->max_instances = 100; /* lower the limit */
+
+ err = snd_timer_global_register(timer);
+ if (err < 0) {
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index cfcc6718aafce..95c5838747754 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -179,7 +179,7 @@ static void snd_timer_request(struct snd_timer_id *tid)
+ *
+ * call this with register_mutex down.
+ */
+-static void snd_timer_check_slave(struct snd_timer_instance *slave)
++static int snd_timer_check_slave(struct snd_timer_instance *slave)
+ {
+ struct snd_timer *timer;
+ struct snd_timer_instance *master;
+@@ -189,16 +189,21 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
+ list_for_each_entry(master, &timer->open_list_head, open_list) {
+ if (slave->slave_class == master->slave_class &&
+ slave->slave_id == master->slave_id) {
++ if (master->timer->num_instances >=
++ master->timer->max_instances)
++ return -EBUSY;
+ list_move_tail(&slave->open_list,
+ &master->slave_list_head);
++ master->timer->num_instances++;
+ spin_lock_irq(&slave_active_lock);
+ slave->master = master;
+ slave->timer = master->timer;
+ spin_unlock_irq(&slave_active_lock);
+- return;
++ return 0;
+ }
+ }
+ }
++ return 0;
+ }
+
+ /*
+@@ -207,7 +212,7 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
+ *
+ * call this with register_mutex down.
+ */
+-static void snd_timer_check_master(struct snd_timer_instance *master)
++static int snd_timer_check_master(struct snd_timer_instance *master)
+ {
+ struct snd_timer_instance *slave, *tmp;
+
+@@ -215,7 +220,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
+ list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
+ if (slave->slave_class == master->slave_class &&
+ slave->slave_id == master->slave_id) {
++ if (master->timer->num_instances >=
++ master->timer->max_instances)
++ return -EBUSY;
+ list_move_tail(&slave->open_list, &master->slave_list_head);
++ master->timer->num_instances++;
+ spin_lock_irq(&slave_active_lock);
+ spin_lock(&master->timer->lock);
+ slave->master = master;
+@@ -227,8 +236,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
+ spin_unlock_irq(&slave_active_lock);
+ }
+ }
++ return 0;
+ }
+
++static int snd_timer_close_locked(struct snd_timer_instance *timeri);
++
+ /*
+ * open a timer instance
+ * when opening a master, the slave id must be here given.
+@@ -239,6 +251,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ {
+ struct snd_timer *timer;
+ struct snd_timer_instance *timeri = NULL;
++ int err;
+
+ if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
+ /* open a slave instance */
+@@ -258,10 +271,14 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ timeri->slave_id = tid->device;
+ timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
+ list_add_tail(&timeri->open_list, &snd_timer_slave_list);
+- snd_timer_check_slave(timeri);
++ err = snd_timer_check_slave(timeri);
++ if (err < 0) {
++ snd_timer_close_locked(timeri);
++ timeri = NULL;
++ }
+ mutex_unlock(®ister_mutex);
+ *ti = timeri;
+- return 0;
++ return err;
+ }
+
+ /* open a master instance */
+@@ -287,6 +304,10 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ return -EBUSY;
+ }
+ }
++ if (timer->num_instances >= timer->max_instances) {
++ mutex_unlock(®ister_mutex);
++ return -EBUSY;
++ }
+ timeri = snd_timer_instance_new(owner, timer);
+ if (!timeri) {
+ mutex_unlock(®ister_mutex);
+@@ -313,25 +334,27 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ }
+
+ list_add_tail(&timeri->open_list, &timer->open_list_head);
+- snd_timer_check_master(timeri);
++ timer->num_instances++;
++ err = snd_timer_check_master(timeri);
++ if (err < 0) {
++ snd_timer_close_locked(timeri);
++ timeri = NULL;
++ }
+ mutex_unlock(®ister_mutex);
+ *ti = timeri;
+- return 0;
++ return err;
+ }
+ EXPORT_SYMBOL(snd_timer_open);
+
+ /*
+ * close a timer instance
++ * call this with register_mutex down.
+ */
+-int snd_timer_close(struct snd_timer_instance *timeri)
++static int snd_timer_close_locked(struct snd_timer_instance *timeri)
+ {
+ struct snd_timer *timer = NULL;
+ struct snd_timer_instance *slave, *tmp;
+
+- if (snd_BUG_ON(!timeri))
+- return -ENXIO;
+-
+- mutex_lock(®ister_mutex);
+ list_del(&timeri->open_list);
+
+ /* force to stop the timer */
+@@ -339,6 +362,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
+
+ timer = timeri->timer;
+ if (timer) {
++ timer->num_instances--;
+ /* wait, until the active callback is finished */
+ spin_lock_irq(&timer->lock);
+ while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
+@@ -354,6 +378,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
+ list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
+ open_list) {
+ list_move_tail(&slave->open_list, &snd_timer_slave_list);
++ timer->num_instances--;
+ slave->master = NULL;
+ slave->timer = NULL;
+ list_del_init(&slave->ack_list);
+@@ -381,9 +406,24 @@ int snd_timer_close(struct snd_timer_instance *timeri)
+ module_put(timer->module);
+ }
+
+- mutex_unlock(®ister_mutex);
+ return 0;
+ }
++
++/*
++ * close a timer instance
++ */
++int snd_timer_close(struct snd_timer_instance *timeri)
++{
++ int err;
++
++ if (snd_BUG_ON(!timeri))
++ return -ENXIO;
++
++ mutex_lock(®ister_mutex);
++ err = snd_timer_close_locked(timeri);
++ mutex_unlock(®ister_mutex);
++ return err;
++}
+ EXPORT_SYMBOL(snd_timer_close);
+
+ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
+@@ -854,6 +894,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
+ spin_lock_init(&timer->lock);
+ tasklet_init(&timer->task_queue, snd_timer_tasklet,
+ (unsigned long)timer);
++ timer->max_instances = 1000; /* default limit per timer */
+ if (card != NULL) {
+ timer->module = card->module;
+ err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);
+--
+2.20.1
+
--- /dev/null
+From 782f1b929d8feb20e52fd731fd2335c78d97fa20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Mar 2019 17:11:10 +0100
+Subject: ALSA: timer: Simplify error path in snd_timer_open()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 41672c0c24a62699d20aab53b98d843b16483053 ]
+
+Just a minor refactoring to use the standard goto for error paths in
+snd_timer_open() instead of open code. The first mutex_lock() is
+moved to the beginning of the function to make the code clearer.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/timer.c | 39 ++++++++++++++++++++-------------------
+ 1 file changed, 20 insertions(+), 19 deletions(-)
+
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index 95c5838747754..6eb4e97662d9c 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -253,19 +253,20 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ struct snd_timer_instance *timeri = NULL;
+ int err;
+
++ mutex_lock(®ister_mutex);
+ if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
+ /* open a slave instance */
+ if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE ||
+ tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) {
+ pr_debug("ALSA: timer: invalid slave class %i\n",
+ tid->dev_sclass);
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock;
+ }
+- mutex_lock(®ister_mutex);
+ timeri = snd_timer_instance_new(owner, NULL);
+ if (!timeri) {
+- mutex_unlock(®ister_mutex);
+- return -ENOMEM;
++ err = -ENOMEM;
++ goto unlock;
+ }
+ timeri->slave_class = tid->dev_sclass;
+ timeri->slave_id = tid->device;
+@@ -276,13 +277,10 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ snd_timer_close_locked(timeri);
+ timeri = NULL;
+ }
+- mutex_unlock(®ister_mutex);
+- *ti = timeri;
+- return err;
++ goto unlock;
+ }
+
+ /* open a master instance */
+- mutex_lock(®ister_mutex);
+ timer = snd_timer_find(tid);
+ #ifdef CONFIG_MODULES
+ if (!timer) {
+@@ -293,25 +291,26 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ }
+ #endif
+ if (!timer) {
+- mutex_unlock(®ister_mutex);
+- return -ENODEV;
++ err = -ENODEV;
++ goto unlock;
+ }
+ if (!list_empty(&timer->open_list_head)) {
+ timeri = list_entry(timer->open_list_head.next,
+ struct snd_timer_instance, open_list);
+ if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
+- mutex_unlock(®ister_mutex);
+- return -EBUSY;
++ err = -EBUSY;
++ timeri = NULL;
++ goto unlock;
+ }
+ }
+ if (timer->num_instances >= timer->max_instances) {
+- mutex_unlock(®ister_mutex);
+- return -EBUSY;
++ err = -EBUSY;
++ goto unlock;
+ }
+ timeri = snd_timer_instance_new(owner, timer);
+ if (!timeri) {
+- mutex_unlock(®ister_mutex);
+- return -ENOMEM;
++ err = -ENOMEM;
++ goto unlock;
+ }
+ /* take a card refcount for safe disconnection */
+ if (timer->card)
+@@ -320,16 +319,16 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ timeri->slave_id = slave_id;
+
+ if (list_empty(&timer->open_list_head) && timer->hw.open) {
+- int err = timer->hw.open(timer);
++ err = timer->hw.open(timer);
+ if (err) {
+ kfree(timeri->owner);
+ kfree(timeri);
++ timeri = NULL;
+
+ if (timer->card)
+ put_device(&timer->card->card_dev);
+ module_put(timer->module);
+- mutex_unlock(®ister_mutex);
+- return err;
++ goto unlock;
+ }
+ }
+
+@@ -340,6 +339,8 @@ int snd_timer_open(struct snd_timer_instance **ti,
+ snd_timer_close_locked(timeri);
+ timeri = NULL;
+ }
++
++ unlock:
+ mutex_unlock(®ister_mutex);
+ *ti = timeri;
+ return err;
+--
+2.20.1
+
sctp-fix-the-issue-that-flags-are-ignored-when-using-kernel_connect.patch
sctp-not-bind-the-socket-in-sctp_connect.patch
xfs-correctly-invert-xfs_buftarg-lru-isolation-logic.patch
+alsa-timer-follow-standard-export_symbol-declaration.patch
+alsa-timer-limit-max-instances-per-timer.patch
+alsa-timer-simplify-error-path-in-snd_timer_open.patch
+alsa-timer-fix-mutex-deadlock-at-releasing-card.patch