diff options
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r-- | sound/core/timer.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index 9a6157ea6881..fc144f43faa6 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -35,6 +35,9 @@ | |||
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | #include <linux/kmod.h> | 36 | #include <linux/kmod.h> |
37 | 37 | ||
38 | /* internal flags */ | ||
39 | #define SNDRV_TIMER_IFLG_PAUSED 0x00010000 | ||
40 | |||
38 | #if IS_ENABLED(CONFIG_SND_HRTIMER) | 41 | #if IS_ENABLED(CONFIG_SND_HRTIMER) |
39 | #define DEFAULT_TIMER_LIMIT 4 | 42 | #define DEFAULT_TIMER_LIMIT 4 |
40 | #else | 43 | #else |
@@ -294,8 +297,21 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
294 | get_device(&timer->card->card_dev); | 297 | get_device(&timer->card->card_dev); |
295 | timeri->slave_class = tid->dev_sclass; | 298 | timeri->slave_class = tid->dev_sclass; |
296 | timeri->slave_id = slave_id; | 299 | timeri->slave_id = slave_id; |
297 | if (list_empty(&timer->open_list_head) && timer->hw.open) | 300 | |
298 | timer->hw.open(timer); | 301 | if (list_empty(&timer->open_list_head) && timer->hw.open) { |
302 | int err = timer->hw.open(timer); | ||
303 | if (err) { | ||
304 | kfree(timeri->owner); | ||
305 | kfree(timeri); | ||
306 | |||
307 | if (timer->card) | ||
308 | put_device(&timer->card->card_dev); | ||
309 | module_put(timer->module); | ||
310 | mutex_unlock(®ister_mutex); | ||
311 | return err; | ||
312 | } | ||
313 | } | ||
314 | |||
299 | list_add_tail(&timeri->open_list, &timer->open_list_head); | 315 | list_add_tail(&timeri->open_list, &timer->open_list_head); |
300 | snd_timer_check_master(timeri); | 316 | snd_timer_check_master(timeri); |
301 | mutex_unlock(®ister_mutex); | 317 | mutex_unlock(®ister_mutex); |
@@ -526,6 +542,10 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) | |||
526 | } | 542 | } |
527 | } | 543 | } |
528 | timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); | 544 | timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); |
545 | if (stop) | ||
546 | timeri->flags &= ~SNDRV_TIMER_IFLG_PAUSED; | ||
547 | else | ||
548 | timeri->flags |= SNDRV_TIMER_IFLG_PAUSED; | ||
529 | snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : | 549 | snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : |
530 | SNDRV_TIMER_EVENT_CONTINUE); | 550 | SNDRV_TIMER_EVENT_CONTINUE); |
531 | unlock: | 551 | unlock: |
@@ -587,6 +607,10 @@ int snd_timer_stop(struct snd_timer_instance *timeri) | |||
587 | */ | 607 | */ |
588 | int snd_timer_continue(struct snd_timer_instance *timeri) | 608 | int snd_timer_continue(struct snd_timer_instance *timeri) |
589 | { | 609 | { |
610 | /* timer can continue only after pause */ | ||
611 | if (!(timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) | ||
612 | return -EINVAL; | ||
613 | |||
590 | if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) | 614 | if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) |
591 | return snd_timer_start_slave(timeri, false); | 615 | return snd_timer_start_slave(timeri, false); |
592 | else | 616 | else |
@@ -813,6 +837,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, | |||
813 | timer->tmr_subdevice = tid->subdevice; | 837 | timer->tmr_subdevice = tid->subdevice; |
814 | if (id) | 838 | if (id) |
815 | strlcpy(timer->id, id, sizeof(timer->id)); | 839 | strlcpy(timer->id, id, sizeof(timer->id)); |
840 | timer->sticks = 1; | ||
816 | INIT_LIST_HEAD(&timer->device_list); | 841 | INIT_LIST_HEAD(&timer->device_list); |
817 | INIT_LIST_HEAD(&timer->open_list_head); | 842 | INIT_LIST_HEAD(&timer->open_list_head); |
818 | INIT_LIST_HEAD(&timer->active_list_head); | 843 | INIT_LIST_HEAD(&timer->active_list_head); |
@@ -1817,6 +1842,9 @@ static int snd_timer_user_continue(struct file *file) | |||
1817 | tu = file->private_data; | 1842 | tu = file->private_data; |
1818 | if (!tu->timeri) | 1843 | if (!tu->timeri) |
1819 | return -EBADFD; | 1844 | return -EBADFD; |
1845 | /* start timer instead of continue if it's not used before */ | ||
1846 | if (!(tu->timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) | ||
1847 | return snd_timer_user_start(file); | ||
1820 | tu->timeri->lost = 0; | 1848 | tu->timeri->lost = 0; |
1821 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1849 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
1822 | } | 1850 | } |
@@ -1958,6 +1986,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1958 | tu->qused--; | 1986 | tu->qused--; |
1959 | spin_unlock_irq(&tu->qlock); | 1987 | spin_unlock_irq(&tu->qlock); |
1960 | 1988 | ||
1989 | mutex_lock(&tu->ioctl_lock); | ||
1961 | if (tu->tread) { | 1990 | if (tu->tread) { |
1962 | if (copy_to_user(buffer, &tu->tqueue[qhead], | 1991 | if (copy_to_user(buffer, &tu->tqueue[qhead], |
1963 | sizeof(struct snd_timer_tread))) | 1992 | sizeof(struct snd_timer_tread))) |
@@ -1967,6 +1996,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1967 | sizeof(struct snd_timer_read))) | 1996 | sizeof(struct snd_timer_read))) |
1968 | err = -EFAULT; | 1997 | err = -EFAULT; |
1969 | } | 1998 | } |
1999 | mutex_unlock(&tu->ioctl_lock); | ||
1970 | 2000 | ||
1971 | spin_lock_irq(&tu->qlock); | 2001 | spin_lock_irq(&tu->qlock); |
1972 | if (err < 0) | 2002 | if (err < 0) |