diff options
author | Takashi Iwai <tiwai@suse.de> | 2016-02-09 17:08:37 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-09 17:08:37 -0500 |
commit | 397da2d0ab0d1398242622d80a74df7245395c63 (patch) | |
tree | 51e01a67c653c67108f65d063b8b9cbfacf0b1a7 /sound | |
parent | b8cb3750ce94d7610934465263850dcf40736bca (diff) | |
parent | 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7 (diff) |
Merge branch 'topic/core-fixes' into for-linus
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/timer.c | 40 | ||||
-rw-r--r-- | sound/drivers/dummy.c | 37 |
2 files changed, 39 insertions, 38 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index 9b513a05765a..dca817fc7894 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -422,7 +422,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
422 | spin_lock_irqsave(&timer->lock, flags); | 422 | spin_lock_irqsave(&timer->lock, flags); |
423 | list_for_each_entry(ts, &ti->slave_active_head, active_list) | 423 | list_for_each_entry(ts, &ti->slave_active_head, active_list) |
424 | if (ts->ccallback) | 424 | if (ts->ccallback) |
425 | ts->ccallback(ti, event + 100, &tstamp, resolution); | 425 | ts->ccallback(ts, event + 100, &tstamp, resolution); |
426 | spin_unlock_irqrestore(&timer->lock, flags); | 426 | spin_unlock_irqrestore(&timer->lock, flags); |
427 | } | 427 | } |
428 | 428 | ||
@@ -518,9 +518,13 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) | |||
518 | spin_unlock_irqrestore(&slave_active_lock, flags); | 518 | spin_unlock_irqrestore(&slave_active_lock, flags); |
519 | return -EBUSY; | 519 | return -EBUSY; |
520 | } | 520 | } |
521 | if (timeri->timer) | ||
522 | spin_lock(&timeri->timer->lock); | ||
521 | timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; | 523 | timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; |
522 | list_del_init(&timeri->ack_list); | 524 | list_del_init(&timeri->ack_list); |
523 | list_del_init(&timeri->active_list); | 525 | list_del_init(&timeri->active_list); |
526 | if (timeri->timer) | ||
527 | spin_unlock(&timeri->timer->lock); | ||
524 | spin_unlock_irqrestore(&slave_active_lock, flags); | 528 | spin_unlock_irqrestore(&slave_active_lock, flags); |
525 | goto __end; | 529 | goto __end; |
526 | } | 530 | } |
@@ -1929,6 +1933,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1929 | { | 1933 | { |
1930 | struct snd_timer_user *tu; | 1934 | struct snd_timer_user *tu; |
1931 | long result = 0, unit; | 1935 | long result = 0, unit; |
1936 | int qhead; | ||
1932 | int err = 0; | 1937 | int err = 0; |
1933 | 1938 | ||
1934 | tu = file->private_data; | 1939 | tu = file->private_data; |
@@ -1940,7 +1945,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1940 | 1945 | ||
1941 | if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { | 1946 | if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { |
1942 | err = -EAGAIN; | 1947 | err = -EAGAIN; |
1943 | break; | 1948 | goto _error; |
1944 | } | 1949 | } |
1945 | 1950 | ||
1946 | set_current_state(TASK_INTERRUPTIBLE); | 1951 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -1955,42 +1960,37 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1955 | 1960 | ||
1956 | if (tu->disconnected) { | 1961 | if (tu->disconnected) { |
1957 | err = -ENODEV; | 1962 | err = -ENODEV; |
1958 | break; | 1963 | goto _error; |
1959 | } | 1964 | } |
1960 | if (signal_pending(current)) { | 1965 | if (signal_pending(current)) { |
1961 | err = -ERESTARTSYS; | 1966 | err = -ERESTARTSYS; |
1962 | break; | 1967 | goto _error; |
1963 | } | 1968 | } |
1964 | } | 1969 | } |
1965 | 1970 | ||
1971 | qhead = tu->qhead++; | ||
1972 | tu->qhead %= tu->queue_size; | ||
1966 | spin_unlock_irq(&tu->qlock); | 1973 | spin_unlock_irq(&tu->qlock); |
1967 | if (err < 0) | ||
1968 | goto _error; | ||
1969 | 1974 | ||
1970 | if (tu->tread) { | 1975 | if (tu->tread) { |
1971 | if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], | 1976 | if (copy_to_user(buffer, &tu->tqueue[qhead], |
1972 | sizeof(struct snd_timer_tread))) { | 1977 | sizeof(struct snd_timer_tread))) |
1973 | err = -EFAULT; | 1978 | err = -EFAULT; |
1974 | goto _error; | ||
1975 | } | ||
1976 | } else { | 1979 | } else { |
1977 | if (copy_to_user(buffer, &tu->queue[tu->qhead++], | 1980 | if (copy_to_user(buffer, &tu->queue[qhead], |
1978 | sizeof(struct snd_timer_read))) { | 1981 | sizeof(struct snd_timer_read))) |
1979 | err = -EFAULT; | 1982 | err = -EFAULT; |
1980 | goto _error; | ||
1981 | } | ||
1982 | } | 1983 | } |
1983 | 1984 | ||
1984 | tu->qhead %= tu->queue_size; | ||
1985 | |||
1986 | result += unit; | ||
1987 | buffer += unit; | ||
1988 | |||
1989 | spin_lock_irq(&tu->qlock); | 1985 | spin_lock_irq(&tu->qlock); |
1990 | tu->qused--; | 1986 | tu->qused--; |
1987 | if (err < 0) | ||
1988 | goto _error; | ||
1989 | result += unit; | ||
1990 | buffer += unit; | ||
1991 | } | 1991 | } |
1992 | spin_unlock_irq(&tu->qlock); | ||
1993 | _error: | 1992 | _error: |
1993 | spin_unlock_irq(&tu->qlock); | ||
1994 | return result > 0 ? result : err; | 1994 | return result > 0 ? result : err; |
1995 | } | 1995 | } |
1996 | 1996 | ||
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index bde33308f0d6..c0f8f613f1f1 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); | |||
87 | module_param(fake_buffer, bool, 0444); | 87 | module_param(fake_buffer, bool, 0444); |
88 | MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); | 88 | MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); |
89 | #ifdef CONFIG_HIGH_RES_TIMERS | 89 | #ifdef CONFIG_HIGH_RES_TIMERS |
90 | module_param(hrtimer, bool, 0444); | 90 | module_param(hrtimer, bool, 0644); |
91 | MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source."); | 91 | MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source."); |
92 | #endif | 92 | #endif |
93 | 93 | ||
@@ -109,6 +109,9 @@ struct dummy_timer_ops { | |||
109 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); | 109 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define get_dummy_ops(substream) \ | ||
113 | (*(const struct dummy_timer_ops **)(substream)->runtime->private_data) | ||
114 | |||
112 | struct dummy_model { | 115 | struct dummy_model { |
113 | const char *name; | 116 | const char *name; |
114 | int (*playback_constraints)(struct snd_pcm_runtime *runtime); | 117 | int (*playback_constraints)(struct snd_pcm_runtime *runtime); |
@@ -137,7 +140,6 @@ struct snd_dummy { | |||
137 | int iobox; | 140 | int iobox; |
138 | struct snd_kcontrol *cd_volume_ctl; | 141 | struct snd_kcontrol *cd_volume_ctl; |
139 | struct snd_kcontrol *cd_switch_ctl; | 142 | struct snd_kcontrol *cd_switch_ctl; |
140 | const struct dummy_timer_ops *timer_ops; | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | /* | 145 | /* |
@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[] = { | |||
231 | */ | 233 | */ |
232 | 234 | ||
233 | struct dummy_systimer_pcm { | 235 | struct dummy_systimer_pcm { |
236 | /* ops must be the first item */ | ||
237 | const struct dummy_timer_ops *timer_ops; | ||
234 | spinlock_t lock; | 238 | spinlock_t lock; |
235 | struct timer_list timer; | 239 | struct timer_list timer; |
236 | unsigned long base_time; | 240 | unsigned long base_time; |
@@ -366,6 +370,8 @@ static const struct dummy_timer_ops dummy_systimer_ops = { | |||
366 | */ | 370 | */ |
367 | 371 | ||
368 | struct dummy_hrtimer_pcm { | 372 | struct dummy_hrtimer_pcm { |
373 | /* ops must be the first item */ | ||
374 | const struct dummy_timer_ops *timer_ops; | ||
369 | ktime_t base_time; | 375 | ktime_t base_time; |
370 | ktime_t period_time; | 376 | ktime_t period_time; |
371 | atomic_t running; | 377 | atomic_t running; |
@@ -492,31 +498,25 @@ static const struct dummy_timer_ops dummy_hrtimer_ops = { | |||
492 | 498 | ||
493 | static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 499 | static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
494 | { | 500 | { |
495 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | ||
496 | |||
497 | switch (cmd) { | 501 | switch (cmd) { |
498 | case SNDRV_PCM_TRIGGER_START: | 502 | case SNDRV_PCM_TRIGGER_START: |
499 | case SNDRV_PCM_TRIGGER_RESUME: | 503 | case SNDRV_PCM_TRIGGER_RESUME: |
500 | return dummy->timer_ops->start(substream); | 504 | return get_dummy_ops(substream)->start(substream); |
501 | case SNDRV_PCM_TRIGGER_STOP: | 505 | case SNDRV_PCM_TRIGGER_STOP: |
502 | case SNDRV_PCM_TRIGGER_SUSPEND: | 506 | case SNDRV_PCM_TRIGGER_SUSPEND: |
503 | return dummy->timer_ops->stop(substream); | 507 | return get_dummy_ops(substream)->stop(substream); |
504 | } | 508 | } |
505 | return -EINVAL; | 509 | return -EINVAL; |
506 | } | 510 | } |
507 | 511 | ||
508 | static int dummy_pcm_prepare(struct snd_pcm_substream *substream) | 512 | static int dummy_pcm_prepare(struct snd_pcm_substream *substream) |
509 | { | 513 | { |
510 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | 514 | return get_dummy_ops(substream)->prepare(substream); |
511 | |||
512 | return dummy->timer_ops->prepare(substream); | ||
513 | } | 515 | } |
514 | 516 | ||
515 | static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) | 517 | static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) |
516 | { | 518 | { |
517 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | 519 | return get_dummy_ops(substream)->pointer(substream); |
518 | |||
519 | return dummy->timer_ops->pointer(substream); | ||
520 | } | 520 | } |
521 | 521 | ||
522 | static struct snd_pcm_hardware dummy_pcm_hardware = { | 522 | static struct snd_pcm_hardware dummy_pcm_hardware = { |
@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream) | |||
562 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | 562 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); |
563 | struct dummy_model *model = dummy->model; | 563 | struct dummy_model *model = dummy->model; |
564 | struct snd_pcm_runtime *runtime = substream->runtime; | 564 | struct snd_pcm_runtime *runtime = substream->runtime; |
565 | const struct dummy_timer_ops *ops; | ||
565 | int err; | 566 | int err; |
566 | 567 | ||
567 | dummy->timer_ops = &dummy_systimer_ops; | 568 | ops = &dummy_systimer_ops; |
568 | #ifdef CONFIG_HIGH_RES_TIMERS | 569 | #ifdef CONFIG_HIGH_RES_TIMERS |
569 | if (hrtimer) | 570 | if (hrtimer) |
570 | dummy->timer_ops = &dummy_hrtimer_ops; | 571 | ops = &dummy_hrtimer_ops; |
571 | #endif | 572 | #endif |
572 | 573 | ||
573 | err = dummy->timer_ops->create(substream); | 574 | err = ops->create(substream); |
574 | if (err < 0) | 575 | if (err < 0) |
575 | return err; | 576 | return err; |
577 | get_dummy_ops(substream) = ops; | ||
576 | 578 | ||
577 | runtime->hw = dummy->pcm_hw; | 579 | runtime->hw = dummy->pcm_hw; |
578 | if (substream->pcm->device & 1) { | 580 | if (substream->pcm->device & 1) { |
@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream) | |||
594 | err = model->capture_constraints(substream->runtime); | 596 | err = model->capture_constraints(substream->runtime); |
595 | } | 597 | } |
596 | if (err < 0) { | 598 | if (err < 0) { |
597 | dummy->timer_ops->free(substream); | 599 | get_dummy_ops(substream)->free(substream); |
598 | return err; | 600 | return err; |
599 | } | 601 | } |
600 | return 0; | 602 | return 0; |
@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream) | |||
602 | 604 | ||
603 | static int dummy_pcm_close(struct snd_pcm_substream *substream) | 605 | static int dummy_pcm_close(struct snd_pcm_substream *substream) |
604 | { | 606 | { |
605 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | 607 | get_dummy_ops(substream)->free(substream); |
606 | dummy->timer_ops->free(substream); | ||
607 | return 0; | 608 | return 0; |
608 | } | 609 | } |
609 | 610 | ||