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) {
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);
}
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;
}