|
@@ -318,25 +318,14 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|
|
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) {
|
|
@@ -345,11 +334,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|
|
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);
|
|
@@ -363,18 +348,27 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
|