diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/compress_offload.c | 2 | ||||
-rw-r--r-- | sound/core/device.c | 9 | ||||
-rw-r--r-- | sound/core/info.c | 6 | ||||
-rw-r--r-- | sound/core/init.c | 4 | ||||
-rw-r--r-- | sound/core/oss/mixer_oss.c | 2 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 2 | ||||
-rw-r--r-- | sound/core/pcm.c | 10 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 10 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 15 | ||||
-rw-r--r-- | sound/core/pcm_local.h | 18 | ||||
-rw-r--r-- | sound/core/pcm_memory.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 261 | ||||
-rw-r--r-- | sound/core/seq/seq_ports.c | 2 | ||||
-rw-r--r-- | sound/core/seq/seq_timer.c | 4 | ||||
-rw-r--r-- | sound/core/timer.c | 48 | ||||
-rw-r--r-- | sound/core/vmaster.c | 16 |
16 files changed, 184 insertions, 227 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 4563432badba..4b01a37c836e 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
@@ -1001,7 +1001,7 @@ static int snd_compress_proc_init(struct snd_compr *compr) | |||
1001 | compr->card->proc_root); | 1001 | compr->card->proc_root); |
1002 | if (!entry) | 1002 | if (!entry) |
1003 | return -ENOMEM; | 1003 | return -ENOMEM; |
1004 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 1004 | entry->mode = S_IFDIR | 0555; |
1005 | if (snd_info_register(entry) < 0) { | 1005 | if (snd_info_register(entry) < 0) { |
1006 | snd_info_free_entry(entry); | 1006 | snd_info_free_entry(entry); |
1007 | return -ENOMEM; | 1007 | return -ENOMEM; |
diff --git a/sound/core/device.c b/sound/core/device.c index cb0e46f66cc9..535102d564e3 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -240,6 +240,15 @@ void snd_device_free_all(struct snd_card *card) | |||
240 | 240 | ||
241 | if (snd_BUG_ON(!card)) | 241 | if (snd_BUG_ON(!card)) |
242 | return; | 242 | return; |
243 | list_for_each_entry_safe_reverse(dev, next, &card->devices, list) { | ||
244 | /* exception: free ctl and lowlevel stuff later */ | ||
245 | if (dev->type == SNDRV_DEV_CONTROL || | ||
246 | dev->type == SNDRV_DEV_LOWLEVEL) | ||
247 | continue; | ||
248 | __snd_device_free(dev); | ||
249 | } | ||
250 | |||
251 | /* free all */ | ||
243 | list_for_each_entry_safe_reverse(dev, next, &card->devices, list) | 252 | list_for_each_entry_safe_reverse(dev, next, &card->devices, list) |
244 | __snd_device_free(dev); | 253 | __snd_device_free(dev); |
245 | } | 254 | } |
diff --git a/sound/core/info.c b/sound/core/info.c index 4b36767af9e1..fe502bc5e6d2 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -454,7 +454,7 @@ static struct snd_info_entry *create_subdir(struct module *mod, | |||
454 | entry = snd_info_create_module_entry(mod, name, NULL); | 454 | entry = snd_info_create_module_entry(mod, name, NULL); |
455 | if (!entry) | 455 | if (!entry) |
456 | return NULL; | 456 | return NULL; |
457 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 457 | entry->mode = S_IFDIR | 0555; |
458 | if (snd_info_register(entry) < 0) { | 458 | if (snd_info_register(entry) < 0) { |
459 | snd_info_free_entry(entry); | 459 | snd_info_free_entry(entry); |
460 | return NULL; | 460 | return NULL; |
@@ -470,7 +470,7 @@ int __init snd_info_init(void) | |||
470 | snd_proc_root = snd_info_create_entry("asound", NULL); | 470 | snd_proc_root = snd_info_create_entry("asound", NULL); |
471 | if (!snd_proc_root) | 471 | if (!snd_proc_root) |
472 | return -ENOMEM; | 472 | return -ENOMEM; |
473 | snd_proc_root->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 473 | snd_proc_root->mode = S_IFDIR | 0555; |
474 | snd_proc_root->p = proc_mkdir("asound", NULL); | 474 | snd_proc_root->p = proc_mkdir("asound", NULL); |
475 | if (!snd_proc_root->p) | 475 | if (!snd_proc_root->p) |
476 | goto error; | 476 | goto error; |
@@ -716,7 +716,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent) | |||
716 | kfree(entry); | 716 | kfree(entry); |
717 | return NULL; | 717 | return NULL; |
718 | } | 718 | } |
719 | entry->mode = S_IFREG | S_IRUGO; | 719 | entry->mode = S_IFREG | 0444; |
720 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 720 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
721 | mutex_init(&entry->access); | 721 | mutex_init(&entry->access); |
722 | INIT_LIST_HEAD(&entry->children); | 722 | INIT_LIST_HEAD(&entry->children); |
diff --git a/sound/core/init.c b/sound/core/init.c index 79b4df1c1dc7..4849c611c0fe 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -703,7 +703,7 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, | |||
703 | return count; | 703 | return count; |
704 | } | 704 | } |
705 | 705 | ||
706 | static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr); | 706 | static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr); |
707 | 707 | ||
708 | static ssize_t | 708 | static ssize_t |
709 | card_number_show_attr(struct device *dev, | 709 | card_number_show_attr(struct device *dev, |
@@ -713,7 +713,7 @@ card_number_show_attr(struct device *dev, | |||
713 | return scnprintf(buf, PAGE_SIZE, "%i\n", card->number); | 713 | return scnprintf(buf, PAGE_SIZE, "%i\n", card->number); |
714 | } | 714 | } |
715 | 715 | ||
716 | static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL); | 716 | static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL); |
717 | 717 | ||
718 | static struct attribute *card_dev_attrs[] = { | 718 | static struct attribute *card_dev_attrs[] = { |
719 | &dev_attr_id.attr, | 719 | &dev_attr_id.attr, |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 379bf486ccc7..64d904bee8bb 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1247,7 +1247,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer) | |||
1247 | if (! entry) | 1247 | if (! entry) |
1248 | return; | 1248 | return; |
1249 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 1249 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
1250 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 1250 | entry->mode = S_IFREG | 0644; |
1251 | entry->c.text.read = snd_mixer_oss_proc_read; | 1251 | entry->c.text.read = snd_mixer_oss_proc_read; |
1252 | entry->c.text.write = snd_mixer_oss_proc_write; | 1252 | entry->c.text.write = snd_mixer_oss_proc_write; |
1253 | entry->private_data = mixer; | 1253 | entry->private_data = mixer; |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 1980f68246cb..905a53c1cde5 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -3045,7 +3045,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) | |||
3045 | continue; | 3045 | continue; |
3046 | if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { | 3046 | if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { |
3047 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 3047 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
3048 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 3048 | entry->mode = S_IFREG | 0644; |
3049 | entry->c.text.read = snd_pcm_oss_proc_read; | 3049 | entry->c.text.read = snd_pcm_oss_proc_read; |
3050 | entry->c.text.write = snd_pcm_oss_proc_write; | 3050 | entry->c.text.write = snd_pcm_oss_proc_write; |
3051 | entry->private_data = pstr; | 3051 | entry->private_data = pstr; |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 66ac89aad681..c352bfb973cc 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -530,7 +530,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) | |||
530 | pcm->card->proc_root); | 530 | pcm->card->proc_root); |
531 | if (!entry) | 531 | if (!entry) |
532 | return -ENOMEM; | 532 | return -ENOMEM; |
533 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 533 | entry->mode = S_IFDIR | 0555; |
534 | if (snd_info_register(entry) < 0) { | 534 | if (snd_info_register(entry) < 0) { |
535 | snd_info_free_entry(entry); | 535 | snd_info_free_entry(entry); |
536 | return -ENOMEM; | 536 | return -ENOMEM; |
@@ -552,7 +552,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) | |||
552 | if (entry) { | 552 | if (entry) { |
553 | entry->c.text.read = snd_pcm_xrun_debug_read; | 553 | entry->c.text.read = snd_pcm_xrun_debug_read; |
554 | entry->c.text.write = snd_pcm_xrun_debug_write; | 554 | entry->c.text.write = snd_pcm_xrun_debug_write; |
555 | entry->mode |= S_IWUSR; | 555 | entry->mode |= 0200; |
556 | entry->private_data = pstr; | 556 | entry->private_data = pstr; |
557 | if (snd_info_register(entry) < 0) { | 557 | if (snd_info_register(entry) < 0) { |
558 | snd_info_free_entry(entry); | 558 | snd_info_free_entry(entry); |
@@ -590,7 +590,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
590 | substream->pstr->proc_root); | 590 | substream->pstr->proc_root); |
591 | if (!entry) | 591 | if (!entry) |
592 | return -ENOMEM; | 592 | return -ENOMEM; |
593 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 593 | entry->mode = S_IFDIR | 0555; |
594 | if (snd_info_register(entry) < 0) { | 594 | if (snd_info_register(entry) < 0) { |
595 | snd_info_free_entry(entry); | 595 | snd_info_free_entry(entry); |
596 | return -ENOMEM; | 596 | return -ENOMEM; |
@@ -647,7 +647,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
647 | entry->private_data = substream; | 647 | entry->private_data = substream; |
648 | entry->c.text.read = NULL; | 648 | entry->c.text.read = NULL; |
649 | entry->c.text.write = snd_pcm_xrun_injection_write; | 649 | entry->c.text.write = snd_pcm_xrun_injection_write; |
650 | entry->mode = S_IFREG | S_IWUSR; | 650 | entry->mode = S_IFREG | 0200; |
651 | if (snd_info_register(entry) < 0) { | 651 | if (snd_info_register(entry) < 0) { |
652 | snd_info_free_entry(entry); | 652 | snd_info_free_entry(entry); |
653 | entry = NULL; | 653 | entry = NULL; |
@@ -1087,7 +1087,7 @@ static ssize_t show_pcm_class(struct device *dev, | |||
1087 | return snprintf(buf, PAGE_SIZE, "%s\n", str); | 1087 | return snprintf(buf, PAGE_SIZE, "%s\n", str); |
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); | 1090 | static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL); |
1091 | static struct attribute *pcm_dev_attrs[] = { | 1091 | static struct attribute *pcm_dev_attrs[] = { |
1092 | &dev_attr_pcm_class.attr, | 1092 | &dev_attr_pcm_class.attr, |
1093 | NULL | 1093 | NULL |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 6491afbb5fd5..39d853bfa5ac 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -45,10 +45,7 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, | |||
45 | 45 | ||
46 | if (get_user(frames, src)) | 46 | if (get_user(frames, src)) |
47 | return -EFAULT; | 47 | return -EFAULT; |
48 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 48 | err = snd_pcm_rewind(substream, frames); |
49 | err = snd_pcm_playback_rewind(substream, frames); | ||
50 | else | ||
51 | err = snd_pcm_capture_rewind(substream, frames); | ||
52 | if (put_user(err, src)) | 49 | if (put_user(err, src)) |
53 | return -EFAULT; | 50 | return -EFAULT; |
54 | return err < 0 ? err : 0; | 51 | return err < 0 ? err : 0; |
@@ -62,10 +59,7 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream, | |||
62 | 59 | ||
63 | if (get_user(frames, src)) | 60 | if (get_user(frames, src)) |
64 | return -EFAULT; | 61 | return -EFAULT; |
65 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 62 | err = snd_pcm_forward(substream, frames); |
66 | err = snd_pcm_playback_forward(substream, frames); | ||
67 | else | ||
68 | err = snd_pcm_capture_forward(substream, frames); | ||
69 | if (put_user(err, src)) | 63 | if (put_user(err, src)) |
70 | return -EFAULT; | 64 | return -EFAULT; |
71 | return err < 0 ? err : 0; | 65 | return err < 0 ? err : 0; |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index f4a19509cccf..44b5ae833082 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -191,10 +191,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, | |||
191 | { | 191 | { |
192 | snd_pcm_uframes_t avail; | 192 | snd_pcm_uframes_t avail; |
193 | 193 | ||
194 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 194 | avail = snd_pcm_avail(substream); |
195 | avail = snd_pcm_playback_avail(runtime); | ||
196 | else | ||
197 | avail = snd_pcm_capture_avail(runtime); | ||
198 | if (avail > runtime->avail_max) | 195 | if (avail > runtime->avail_max) |
199 | runtime->avail_max = avail; | 196 | runtime->avail_max = avail; |
200 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | 197 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { |
@@ -1856,10 +1853,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
1856 | * This check must happen after been added to the waitqueue | 1853 | * This check must happen after been added to the waitqueue |
1857 | * and having current state be INTERRUPTIBLE. | 1854 | * and having current state be INTERRUPTIBLE. |
1858 | */ | 1855 | */ |
1859 | if (is_playback) | 1856 | avail = snd_pcm_avail(substream); |
1860 | avail = snd_pcm_playback_avail(runtime); | ||
1861 | else | ||
1862 | avail = snd_pcm_capture_avail(runtime); | ||
1863 | if (avail >= runtime->twake) | 1857 | if (avail >= runtime->twake) |
1864 | break; | 1858 | break; |
1865 | snd_pcm_stream_unlock_irq(substream); | 1859 | snd_pcm_stream_unlock_irq(substream); |
@@ -2175,10 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, | |||
2175 | runtime->twake = runtime->control->avail_min ? : 1; | 2169 | runtime->twake = runtime->control->avail_min ? : 1; |
2176 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 2170 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
2177 | snd_pcm_update_hw_ptr(substream); | 2171 | snd_pcm_update_hw_ptr(substream); |
2178 | if (is_playback) | 2172 | avail = snd_pcm_avail(substream); |
2179 | avail = snd_pcm_playback_avail(runtime); | ||
2180 | else | ||
2181 | avail = snd_pcm_capture_avail(runtime); | ||
2182 | while (size > 0) { | 2173 | while (size > 0) { |
2183 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 2174 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
2184 | snd_pcm_uframes_t cont; | 2175 | snd_pcm_uframes_t cont; |
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index 16f254732b2a..7a499d02df6c 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h | |||
@@ -36,6 +36,24 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | |||
36 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, | 36 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, |
37 | snd_pcm_uframes_t new_hw_ptr); | 37 | snd_pcm_uframes_t new_hw_ptr); |
38 | 38 | ||
39 | static inline snd_pcm_uframes_t | ||
40 | snd_pcm_avail(struct snd_pcm_substream *substream) | ||
41 | { | ||
42 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
43 | return snd_pcm_playback_avail(substream->runtime); | ||
44 | else | ||
45 | return snd_pcm_capture_avail(substream->runtime); | ||
46 | } | ||
47 | |||
48 | static inline snd_pcm_uframes_t | ||
49 | snd_pcm_hw_avail(struct snd_pcm_substream *substream) | ||
50 | { | ||
51 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
52 | return snd_pcm_playback_hw_avail(substream->runtime); | ||
53 | else | ||
54 | return snd_pcm_capture_hw_avail(substream->runtime); | ||
55 | } | ||
56 | |||
39 | #ifdef CONFIG_SND_PCM_TIMER | 57 | #ifdef CONFIG_SND_PCM_TIMER |
40 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); | 58 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); |
41 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); | 59 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); |
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index ae33e456708c..4b5356a10315 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -201,7 +201,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream) | |||
201 | if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { | 201 | if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { |
202 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; | 202 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; |
203 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; | 203 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; |
204 | entry->mode |= S_IWUSR; | 204 | entry->mode |= 0200; |
205 | entry->private_data = substream; | 205 | entry->private_data = substream; |
206 | if (snd_info_register(entry) < 0) { | 206 | if (snd_info_register(entry) < 0) { |
207 | snd_info_free_entry(entry); | 207 | snd_info_free_entry(entry); |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0e875d5a9e86..04c6301394d0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -99,6 +99,57 @@ static inline void down_write_nonblock(struct rw_semaphore *lock) | |||
99 | cond_resched(); | 99 | cond_resched(); |
100 | } | 100 | } |
101 | 101 | ||
102 | #define PCM_LOCK_DEFAULT 0 | ||
103 | #define PCM_LOCK_IRQ 1 | ||
104 | #define PCM_LOCK_IRQSAVE 2 | ||
105 | |||
106 | static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream, | ||
107 | unsigned int mode) | ||
108 | { | ||
109 | unsigned long flags = 0; | ||
110 | if (substream->pcm->nonatomic) { | ||
111 | down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING); | ||
112 | mutex_lock(&substream->self_group.mutex); | ||
113 | } else { | ||
114 | switch (mode) { | ||
115 | case PCM_LOCK_DEFAULT: | ||
116 | read_lock(&snd_pcm_link_rwlock); | ||
117 | break; | ||
118 | case PCM_LOCK_IRQ: | ||
119 | read_lock_irq(&snd_pcm_link_rwlock); | ||
120 | break; | ||
121 | case PCM_LOCK_IRQSAVE: | ||
122 | read_lock_irqsave(&snd_pcm_link_rwlock, flags); | ||
123 | break; | ||
124 | } | ||
125 | spin_lock(&substream->self_group.lock); | ||
126 | } | ||
127 | return flags; | ||
128 | } | ||
129 | |||
130 | static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream, | ||
131 | unsigned int mode, unsigned long flags) | ||
132 | { | ||
133 | if (substream->pcm->nonatomic) { | ||
134 | mutex_unlock(&substream->self_group.mutex); | ||
135 | up_read(&snd_pcm_link_rwsem); | ||
136 | } else { | ||
137 | spin_unlock(&substream->self_group.lock); | ||
138 | |||
139 | switch (mode) { | ||
140 | case PCM_LOCK_DEFAULT: | ||
141 | read_unlock(&snd_pcm_link_rwlock); | ||
142 | break; | ||
143 | case PCM_LOCK_IRQ: | ||
144 | read_unlock_irq(&snd_pcm_link_rwlock); | ||
145 | break; | ||
146 | case PCM_LOCK_IRQSAVE: | ||
147 | read_unlock_irqrestore(&snd_pcm_link_rwlock, flags); | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
102 | /** | 153 | /** |
103 | * snd_pcm_stream_lock - Lock the PCM stream | 154 | * snd_pcm_stream_lock - Lock the PCM stream |
104 | * @substream: PCM substream | 155 | * @substream: PCM substream |
@@ -109,13 +160,7 @@ static inline void down_write_nonblock(struct rw_semaphore *lock) | |||
109 | */ | 160 | */ |
110 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream) | 161 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream) |
111 | { | 162 | { |
112 | if (substream->pcm->nonatomic) { | 163 | __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT); |
113 | down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING); | ||
114 | mutex_lock(&substream->self_group.mutex); | ||
115 | } else { | ||
116 | read_lock(&snd_pcm_link_rwlock); | ||
117 | spin_lock(&substream->self_group.lock); | ||
118 | } | ||
119 | } | 164 | } |
120 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); | 165 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); |
121 | 166 | ||
@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); | |||
127 | */ | 172 | */ |
128 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) | 173 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) |
129 | { | 174 | { |
130 | if (substream->pcm->nonatomic) { | 175 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0); |
131 | mutex_unlock(&substream->self_group.mutex); | ||
132 | up_read(&snd_pcm_link_rwsem); | ||
133 | } else { | ||
134 | spin_unlock(&substream->self_group.lock); | ||
135 | read_unlock(&snd_pcm_link_rwlock); | ||
136 | } | ||
137 | } | 176 | } |
138 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); | 177 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); |
139 | 178 | ||
@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); | |||
147 | */ | 186 | */ |
148 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) | 187 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) |
149 | { | 188 | { |
150 | if (!substream->pcm->nonatomic) | 189 | __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ); |
151 | local_irq_disable(); | ||
152 | snd_pcm_stream_lock(substream); | ||
153 | } | 190 | } |
154 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); | 191 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); |
155 | 192 | ||
@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); | |||
161 | */ | 198 | */ |
162 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) | 199 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) |
163 | { | 200 | { |
164 | snd_pcm_stream_unlock(substream); | 201 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0); |
165 | if (!substream->pcm->nonatomic) | ||
166 | local_irq_enable(); | ||
167 | } | 202 | } |
168 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); | 203 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); |
169 | 204 | ||
170 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) | 205 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) |
171 | { | 206 | { |
172 | unsigned long flags = 0; | 207 | return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE); |
173 | if (!substream->pcm->nonatomic) | ||
174 | local_irq_save(flags); | ||
175 | snd_pcm_stream_lock(substream); | ||
176 | return flags; | ||
177 | } | 208 | } |
178 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | 209 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); |
179 | 210 | ||
@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | |||
187 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, | 218 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, |
188 | unsigned long flags) | 219 | unsigned long flags) |
189 | { | 220 | { |
190 | snd_pcm_stream_unlock(substream); | 221 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags); |
191 | if (!substream->pcm->nonatomic) | ||
192 | local_irq_restore(flags); | ||
193 | } | 222 | } |
194 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); | 223 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); |
195 | 224 | ||
@@ -857,6 +886,18 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, | |||
857 | return err; | 886 | return err; |
858 | } | 887 | } |
859 | 888 | ||
889 | static inline snd_pcm_uframes_t | ||
890 | snd_pcm_calc_delay(struct snd_pcm_substream *substream) | ||
891 | { | ||
892 | snd_pcm_uframes_t delay; | ||
893 | |||
894 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
895 | delay = snd_pcm_playback_hw_avail(substream->runtime); | ||
896 | else | ||
897 | delay = snd_pcm_capture_avail(substream->runtime); | ||
898 | return delay + substream->runtime->delay; | ||
899 | } | ||
900 | |||
860 | int snd_pcm_status(struct snd_pcm_substream *substream, | 901 | int snd_pcm_status(struct snd_pcm_substream *substream, |
861 | struct snd_pcm_status *status) | 902 | struct snd_pcm_status *status) |
862 | { | 903 | { |
@@ -908,21 +949,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
908 | _tstamp_end: | 949 | _tstamp_end: |
909 | status->appl_ptr = runtime->control->appl_ptr; | 950 | status->appl_ptr = runtime->control->appl_ptr; |
910 | status->hw_ptr = runtime->status->hw_ptr; | 951 | status->hw_ptr = runtime->status->hw_ptr; |
911 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 952 | status->avail = snd_pcm_avail(substream); |
912 | status->avail = snd_pcm_playback_avail(runtime); | 953 | status->delay = snd_pcm_running(substream) ? |
913 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING || | 954 | snd_pcm_calc_delay(substream) : 0; |
914 | runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | ||
915 | status->delay = runtime->buffer_size - status->avail; | ||
916 | status->delay += runtime->delay; | ||
917 | } else | ||
918 | status->delay = 0; | ||
919 | } else { | ||
920 | status->avail = snd_pcm_capture_avail(runtime); | ||
921 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
922 | status->delay = status->avail + runtime->delay; | ||
923 | else | ||
924 | status->delay = 0; | ||
925 | } | ||
926 | status->avail_max = runtime->avail_max; | 955 | status->avail_max = runtime->avail_max; |
927 | status->overrange = runtime->overrange; | 956 | status->overrange = runtime->overrange; |
928 | runtime->avail_max = 0; | 957 | runtime->avail_max = 0; |
@@ -2610,10 +2639,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream, | |||
2610 | return ret < 0 ? 0 : frames; | 2639 | return ret < 0 ? 0 : frames; |
2611 | } | 2640 | } |
2612 | 2641 | ||
2613 | static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, | 2642 | static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream, |
2614 | snd_pcm_uframes_t frames) | 2643 | snd_pcm_uframes_t frames) |
2615 | { | 2644 | { |
2616 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2617 | snd_pcm_sframes_t ret; | 2645 | snd_pcm_sframes_t ret; |
2618 | 2646 | ||
2619 | if (frames == 0) | 2647 | if (frames == 0) |
@@ -2623,33 +2651,14 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst | |||
2623 | ret = do_pcm_hwsync(substream); | 2651 | ret = do_pcm_hwsync(substream); |
2624 | if (!ret) | 2652 | if (!ret) |
2625 | ret = rewind_appl_ptr(substream, frames, | 2653 | ret = rewind_appl_ptr(substream, frames, |
2626 | snd_pcm_playback_hw_avail(runtime)); | 2654 | snd_pcm_hw_avail(substream)); |
2627 | snd_pcm_stream_unlock_irq(substream); | 2655 | snd_pcm_stream_unlock_irq(substream); |
2628 | return ret; | 2656 | return ret; |
2629 | } | 2657 | } |
2630 | 2658 | ||
2631 | static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream, | 2659 | static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream, |
2632 | snd_pcm_uframes_t frames) | 2660 | snd_pcm_uframes_t frames) |
2633 | { | 2661 | { |
2634 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2635 | snd_pcm_sframes_t ret; | ||
2636 | |||
2637 | if (frames == 0) | ||
2638 | return 0; | ||
2639 | |||
2640 | snd_pcm_stream_lock_irq(substream); | ||
2641 | ret = do_pcm_hwsync(substream); | ||
2642 | if (!ret) | ||
2643 | ret = rewind_appl_ptr(substream, frames, | ||
2644 | snd_pcm_capture_hw_avail(runtime)); | ||
2645 | snd_pcm_stream_unlock_irq(substream); | ||
2646 | return ret; | ||
2647 | } | ||
2648 | |||
2649 | static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream, | ||
2650 | snd_pcm_uframes_t frames) | ||
2651 | { | ||
2652 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2653 | snd_pcm_sframes_t ret; | 2662 | snd_pcm_sframes_t ret; |
2654 | 2663 | ||
2655 | if (frames == 0) | 2664 | if (frames == 0) |
@@ -2659,25 +2668,7 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs | |||
2659 | ret = do_pcm_hwsync(substream); | 2668 | ret = do_pcm_hwsync(substream); |
2660 | if (!ret) | 2669 | if (!ret) |
2661 | ret = forward_appl_ptr(substream, frames, | 2670 | ret = forward_appl_ptr(substream, frames, |
2662 | snd_pcm_playback_avail(runtime)); | 2671 | snd_pcm_avail(substream)); |
2663 | snd_pcm_stream_unlock_irq(substream); | ||
2664 | return ret; | ||
2665 | } | ||
2666 | |||
2667 | static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream, | ||
2668 | snd_pcm_uframes_t frames) | ||
2669 | { | ||
2670 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2671 | snd_pcm_sframes_t ret; | ||
2672 | |||
2673 | if (frames == 0) | ||
2674 | return 0; | ||
2675 | |||
2676 | snd_pcm_stream_lock_irq(substream); | ||
2677 | ret = do_pcm_hwsync(substream); | ||
2678 | if (!ret) | ||
2679 | ret = forward_appl_ptr(substream, frames, | ||
2680 | snd_pcm_capture_avail(runtime)); | ||
2681 | snd_pcm_stream_unlock_irq(substream); | 2672 | snd_pcm_stream_unlock_irq(substream); |
2682 | return ret; | 2673 | return ret; |
2683 | } | 2674 | } |
@@ -2695,19 +2686,13 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream) | |||
2695 | static int snd_pcm_delay(struct snd_pcm_substream *substream, | 2686 | static int snd_pcm_delay(struct snd_pcm_substream *substream, |
2696 | snd_pcm_sframes_t *delay) | 2687 | snd_pcm_sframes_t *delay) |
2697 | { | 2688 | { |
2698 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2699 | int err; | 2689 | int err; |
2700 | snd_pcm_sframes_t n = 0; | 2690 | snd_pcm_sframes_t n = 0; |
2701 | 2691 | ||
2702 | snd_pcm_stream_lock_irq(substream); | 2692 | snd_pcm_stream_lock_irq(substream); |
2703 | err = do_pcm_hwsync(substream); | 2693 | err = do_pcm_hwsync(substream); |
2704 | if (!err) { | 2694 | if (!err) |
2705 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2695 | n = snd_pcm_calc_delay(substream); |
2706 | n = snd_pcm_playback_hw_avail(runtime); | ||
2707 | else | ||
2708 | n = snd_pcm_capture_avail(runtime); | ||
2709 | n += runtime->delay; | ||
2710 | } | ||
2711 | snd_pcm_stream_unlock_irq(substream); | 2696 | snd_pcm_stream_unlock_irq(substream); |
2712 | if (!err) | 2697 | if (!err) |
2713 | *delay = n; | 2698 | *delay = n; |
@@ -2834,10 +2819,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream, | |||
2834 | return -EFAULT; | 2819 | return -EFAULT; |
2835 | if (put_user(0, _frames)) | 2820 | if (put_user(0, _frames)) |
2836 | return -EFAULT; | 2821 | return -EFAULT; |
2837 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2822 | result = snd_pcm_rewind(substream, frames); |
2838 | result = snd_pcm_playback_rewind(substream, frames); | ||
2839 | else | ||
2840 | result = snd_pcm_capture_rewind(substream, frames); | ||
2841 | __put_user(result, _frames); | 2823 | __put_user(result, _frames); |
2842 | return result < 0 ? result : 0; | 2824 | return result < 0 ? result : 0; |
2843 | } | 2825 | } |
@@ -2852,10 +2834,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream, | |||
2852 | return -EFAULT; | 2834 | return -EFAULT; |
2853 | if (put_user(0, _frames)) | 2835 | if (put_user(0, _frames)) |
2854 | return -EFAULT; | 2836 | return -EFAULT; |
2855 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2837 | result = snd_pcm_forward(substream, frames); |
2856 | result = snd_pcm_playback_forward(substream, frames); | ||
2857 | else | ||
2858 | result = snd_pcm_capture_forward(substream, frames); | ||
2859 | __put_user(result, _frames); | 2838 | __put_user(result, _frames); |
2860 | return result < 0 ? result : 0; | 2839 | return result < 0 ? result : 0; |
2861 | } | 2840 | } |
@@ -2998,7 +2977,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | |||
2998 | /* provided only for OSS; capture-only and no value returned */ | 2977 | /* provided only for OSS; capture-only and no value returned */ |
2999 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | 2978 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) |
3000 | return -EINVAL; | 2979 | return -EINVAL; |
3001 | result = snd_pcm_capture_forward(substream, *frames); | 2980 | result = snd_pcm_forward(substream, *frames); |
3002 | return result < 0 ? result : 0; | 2981 | return result < 0 ? result : 0; |
3003 | } | 2982 | } |
3004 | case SNDRV_PCM_IOCTL_HW_PARAMS: | 2983 | case SNDRV_PCM_IOCTL_HW_PARAMS: |
@@ -3140,82 +3119,46 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) | |||
3140 | return result; | 3119 | return result; |
3141 | } | 3120 | } |
3142 | 3121 | ||
3143 | static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait) | 3122 | static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) |
3144 | { | 3123 | { |
3145 | struct snd_pcm_file *pcm_file; | 3124 | struct snd_pcm_file *pcm_file; |
3146 | struct snd_pcm_substream *substream; | 3125 | struct snd_pcm_substream *substream; |
3147 | struct snd_pcm_runtime *runtime; | 3126 | struct snd_pcm_runtime *runtime; |
3148 | __poll_t mask; | 3127 | __poll_t mask, ok; |
3149 | snd_pcm_uframes_t avail; | 3128 | snd_pcm_uframes_t avail; |
3150 | 3129 | ||
3151 | pcm_file = file->private_data; | 3130 | pcm_file = file->private_data; |
3152 | 3131 | ||
3153 | substream = pcm_file->substream; | 3132 | substream = pcm_file->substream; |
3133 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
3134 | ok = EPOLLOUT | EPOLLWRNORM; | ||
3135 | else | ||
3136 | ok = EPOLLIN | EPOLLRDNORM; | ||
3154 | if (PCM_RUNTIME_CHECK(substream)) | 3137 | if (PCM_RUNTIME_CHECK(substream)) |
3155 | return EPOLLOUT | EPOLLWRNORM | EPOLLERR; | 3138 | return ok | EPOLLERR; |
3156 | runtime = substream->runtime; | ||
3157 | |||
3158 | poll_wait(file, &runtime->sleep, wait); | ||
3159 | 3139 | ||
3160 | snd_pcm_stream_lock_irq(substream); | ||
3161 | avail = snd_pcm_playback_avail(runtime); | ||
3162 | switch (runtime->status->state) { | ||
3163 | case SNDRV_PCM_STATE_RUNNING: | ||
3164 | case SNDRV_PCM_STATE_PREPARED: | ||
3165 | case SNDRV_PCM_STATE_PAUSED: | ||
3166 | if (avail >= runtime->control->avail_min) { | ||
3167 | mask = EPOLLOUT | EPOLLWRNORM; | ||
3168 | break; | ||
3169 | } | ||
3170 | /* Fall through */ | ||
3171 | case SNDRV_PCM_STATE_DRAINING: | ||
3172 | mask = 0; | ||
3173 | break; | ||
3174 | default: | ||
3175 | mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR; | ||
3176 | break; | ||
3177 | } | ||
3178 | snd_pcm_stream_unlock_irq(substream); | ||
3179 | return mask; | ||
3180 | } | ||
3181 | |||
3182 | static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait) | ||
3183 | { | ||
3184 | struct snd_pcm_file *pcm_file; | ||
3185 | struct snd_pcm_substream *substream; | ||
3186 | struct snd_pcm_runtime *runtime; | ||
3187 | __poll_t mask; | ||
3188 | snd_pcm_uframes_t avail; | ||
3189 | |||
3190 | pcm_file = file->private_data; | ||
3191 | |||
3192 | substream = pcm_file->substream; | ||
3193 | if (PCM_RUNTIME_CHECK(substream)) | ||
3194 | return EPOLLIN | EPOLLRDNORM | EPOLLERR; | ||
3195 | runtime = substream->runtime; | 3140 | runtime = substream->runtime; |
3196 | |||
3197 | poll_wait(file, &runtime->sleep, wait); | 3141 | poll_wait(file, &runtime->sleep, wait); |
3198 | 3142 | ||
3143 | mask = 0; | ||
3199 | snd_pcm_stream_lock_irq(substream); | 3144 | snd_pcm_stream_lock_irq(substream); |
3200 | avail = snd_pcm_capture_avail(runtime); | 3145 | avail = snd_pcm_avail(substream); |
3201 | switch (runtime->status->state) { | 3146 | switch (runtime->status->state) { |
3202 | case SNDRV_PCM_STATE_RUNNING: | 3147 | case SNDRV_PCM_STATE_RUNNING: |
3203 | case SNDRV_PCM_STATE_PREPARED: | 3148 | case SNDRV_PCM_STATE_PREPARED: |
3204 | case SNDRV_PCM_STATE_PAUSED: | 3149 | case SNDRV_PCM_STATE_PAUSED: |
3205 | if (avail >= runtime->control->avail_min) { | 3150 | if (avail >= runtime->control->avail_min) |
3206 | mask = EPOLLIN | EPOLLRDNORM; | 3151 | mask = ok; |
3207 | break; | ||
3208 | } | ||
3209 | mask = 0; | ||
3210 | break; | 3152 | break; |
3211 | case SNDRV_PCM_STATE_DRAINING: | 3153 | case SNDRV_PCM_STATE_DRAINING: |
3212 | if (avail > 0) { | 3154 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
3213 | mask = EPOLLIN | EPOLLRDNORM; | 3155 | mask = ok; |
3214 | break; | 3156 | if (!avail) |
3157 | mask |= EPOLLERR; | ||
3215 | } | 3158 | } |
3216 | /* Fall through */ | 3159 | break; |
3217 | default: | 3160 | default: |
3218 | mask = EPOLLIN | EPOLLRDNORM | EPOLLERR; | 3161 | mask = ok | EPOLLERR; |
3219 | break; | 3162 | break; |
3220 | } | 3163 | } |
3221 | snd_pcm_stream_unlock_irq(substream); | 3164 | snd_pcm_stream_unlock_irq(substream); |
@@ -3707,7 +3650,7 @@ const struct file_operations snd_pcm_f_ops[2] = { | |||
3707 | .open = snd_pcm_playback_open, | 3650 | .open = snd_pcm_playback_open, |
3708 | .release = snd_pcm_release, | 3651 | .release = snd_pcm_release, |
3709 | .llseek = no_llseek, | 3652 | .llseek = no_llseek, |
3710 | .poll = snd_pcm_playback_poll, | 3653 | .poll = snd_pcm_poll, |
3711 | .unlocked_ioctl = snd_pcm_ioctl, | 3654 | .unlocked_ioctl = snd_pcm_ioctl, |
3712 | .compat_ioctl = snd_pcm_ioctl_compat, | 3655 | .compat_ioctl = snd_pcm_ioctl_compat, |
3713 | .mmap = snd_pcm_mmap, | 3656 | .mmap = snd_pcm_mmap, |
@@ -3721,7 +3664,7 @@ const struct file_operations snd_pcm_f_ops[2] = { | |||
3721 | .open = snd_pcm_capture_open, | 3664 | .open = snd_pcm_capture_open, |
3722 | .release = snd_pcm_release, | 3665 | .release = snd_pcm_release, |
3723 | .llseek = no_llseek, | 3666 | .llseek = no_llseek, |
3724 | .poll = snd_pcm_capture_poll, | 3667 | .poll = snd_pcm_poll, |
3725 | .unlocked_ioctl = snd_pcm_ioctl, | 3668 | .unlocked_ioctl = snd_pcm_ioctl, |
3726 | .compat_ioctl = snd_pcm_ioctl_compat, | 3669 | .compat_ioctl = snd_pcm_ioctl_compat, |
3727 | .mmap = snd_pcm_mmap, | 3670 | .mmap = snd_pcm_mmap, |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index d21ece9f8d73..24d90abfc64d 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -669,7 +669,7 @@ int snd_seq_event_port_attach(int client, | |||
669 | /* Set up the port */ | 669 | /* Set up the port */ |
670 | memset(&portinfo, 0, sizeof(portinfo)); | 670 | memset(&portinfo, 0, sizeof(portinfo)); |
671 | portinfo.addr.client = client; | 671 | portinfo.addr.client = client; |
672 | strlcpy(portinfo.name, portname ? portname : "Unamed port", | 672 | strlcpy(portinfo.name, portname ? portname : "Unnamed port", |
673 | sizeof(portinfo.name)); | 673 | sizeof(portinfo.name)); |
674 | 674 | ||
675 | portinfo.capability = cap; | 675 | portinfo.capability = cap; |
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 23167578231f..f587d0e27476 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -371,9 +371,7 @@ static int initialize_timer(struct snd_seq_timer *tmr) | |||
371 | 371 | ||
372 | tmr->ticks = 1; | 372 | tmr->ticks = 1; |
373 | if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { | 373 | if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { |
374 | unsigned long r = t->hw.resolution; | 374 | unsigned long r = snd_timer_resolution(tmr->timeri); |
375 | if (! r && t->hw.c_resolution) | ||
376 | r = t->hw.c_resolution(t); | ||
377 | if (r) { | 375 | if (r) { |
378 | tmr->ticks = (unsigned int)(1000000000uL / (r * freq)); | 376 | tmr->ticks = (unsigned int)(1000000000uL / (r * freq)); |
379 | if (! tmr->ticks) | 377 | if (! tmr->ticks) |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 0ddcae495838..665089c45560 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -427,25 +427,35 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
427 | } | 427 | } |
428 | EXPORT_SYMBOL(snd_timer_close); | 428 | EXPORT_SYMBOL(snd_timer_close); |
429 | 429 | ||
430 | static unsigned long snd_timer_hw_resolution(struct snd_timer *timer) | ||
431 | { | ||
432 | if (timer->hw.c_resolution) | ||
433 | return timer->hw.c_resolution(timer); | ||
434 | else | ||
435 | return timer->hw.resolution; | ||
436 | } | ||
437 | |||
430 | unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) | 438 | unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) |
431 | { | 439 | { |
432 | struct snd_timer * timer; | 440 | struct snd_timer * timer; |
441 | unsigned long ret = 0; | ||
442 | unsigned long flags; | ||
433 | 443 | ||
434 | if (timeri == NULL) | 444 | if (timeri == NULL) |
435 | return 0; | 445 | return 0; |
436 | timer = timeri->timer; | 446 | timer = timeri->timer; |
437 | if (timer) { | 447 | if (timer) { |
438 | if (timer->hw.c_resolution) | 448 | spin_lock_irqsave(&timer->lock, flags); |
439 | return timer->hw.c_resolution(timer); | 449 | ret = snd_timer_hw_resolution(timer); |
440 | return timer->hw.resolution; | 450 | spin_unlock_irqrestore(&timer->lock, flags); |
441 | } | 451 | } |
442 | return 0; | 452 | return ret; |
443 | } | 453 | } |
444 | EXPORT_SYMBOL(snd_timer_resolution); | 454 | EXPORT_SYMBOL(snd_timer_resolution); |
445 | 455 | ||
446 | static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | 456 | static void snd_timer_notify1(struct snd_timer_instance *ti, int event) |
447 | { | 457 | { |
448 | struct snd_timer *timer; | 458 | struct snd_timer *timer = ti->timer; |
449 | unsigned long resolution = 0; | 459 | unsigned long resolution = 0; |
450 | struct snd_timer_instance *ts; | 460 | struct snd_timer_instance *ts; |
451 | struct timespec tstamp; | 461 | struct timespec tstamp; |
@@ -457,14 +467,14 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
457 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || | 467 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || |
458 | event > SNDRV_TIMER_EVENT_PAUSE)) | 468 | event > SNDRV_TIMER_EVENT_PAUSE)) |
459 | return; | 469 | return; |
460 | if (event == SNDRV_TIMER_EVENT_START || | 470 | if (timer && |
461 | event == SNDRV_TIMER_EVENT_CONTINUE) | 471 | (event == SNDRV_TIMER_EVENT_START || |
462 | resolution = snd_timer_resolution(ti); | 472 | event == SNDRV_TIMER_EVENT_CONTINUE)) |
473 | resolution = snd_timer_hw_resolution(timer); | ||
463 | if (ti->ccallback) | 474 | if (ti->ccallback) |
464 | ti->ccallback(ti, event, &tstamp, resolution); | 475 | ti->ccallback(ti, event, &tstamp, resolution); |
465 | if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) | 476 | if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) |
466 | return; | 477 | return; |
467 | timer = ti->timer; | ||
468 | if (timer == NULL) | 478 | if (timer == NULL) |
469 | return; | 479 | return; |
470 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) | 480 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) |
@@ -771,10 +781,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | |||
771 | spin_lock_irqsave(&timer->lock, flags); | 781 | spin_lock_irqsave(&timer->lock, flags); |
772 | 782 | ||
773 | /* remember the current resolution */ | 783 | /* remember the current resolution */ |
774 | if (timer->hw.c_resolution) | 784 | resolution = snd_timer_hw_resolution(timer); |
775 | resolution = timer->hw.c_resolution(timer); | ||
776 | else | ||
777 | resolution = timer->hw.resolution; | ||
778 | 785 | ||
779 | /* loop for all active instances | 786 | /* loop for all active instances |
780 | * Here we cannot use list_for_each_entry because the active_list of a | 787 | * Here we cannot use list_for_each_entry because the active_list of a |
@@ -1014,12 +1021,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam | |||
1014 | spin_lock_irqsave(&timer->lock, flags); | 1021 | spin_lock_irqsave(&timer->lock, flags); |
1015 | if (event == SNDRV_TIMER_EVENT_MSTART || | 1022 | if (event == SNDRV_TIMER_EVENT_MSTART || |
1016 | event == SNDRV_TIMER_EVENT_MCONTINUE || | 1023 | event == SNDRV_TIMER_EVENT_MCONTINUE || |
1017 | event == SNDRV_TIMER_EVENT_MRESUME) { | 1024 | event == SNDRV_TIMER_EVENT_MRESUME) |
1018 | if (timer->hw.c_resolution) | 1025 | resolution = snd_timer_hw_resolution(timer); |
1019 | resolution = timer->hw.c_resolution(timer); | ||
1020 | else | ||
1021 | resolution = timer->hw.resolution; | ||
1022 | } | ||
1023 | list_for_each_entry(ti, &timer->active_list_head, active_list) { | 1026 | list_for_each_entry(ti, &timer->active_list_head, active_list) { |
1024 | if (ti->ccallback) | 1027 | if (ti->ccallback) |
1025 | ti->ccallback(ti, event, tstamp, resolution); | 1028 | ti->ccallback(ti, event, tstamp, resolution); |
@@ -1656,10 +1659,8 @@ static int snd_timer_user_gstatus(struct file *file, | |||
1656 | mutex_lock(®ister_mutex); | 1659 | mutex_lock(®ister_mutex); |
1657 | t = snd_timer_find(&tid); | 1660 | t = snd_timer_find(&tid); |
1658 | if (t != NULL) { | 1661 | if (t != NULL) { |
1659 | if (t->hw.c_resolution) | 1662 | spin_lock_irq(&t->lock); |
1660 | gstatus.resolution = t->hw.c_resolution(t); | 1663 | gstatus.resolution = snd_timer_hw_resolution(t); |
1661 | else | ||
1662 | gstatus.resolution = t->hw.resolution; | ||
1663 | if (t->hw.precise_resolution) { | 1664 | if (t->hw.precise_resolution) { |
1664 | t->hw.precise_resolution(t, &gstatus.resolution_num, | 1665 | t->hw.precise_resolution(t, &gstatus.resolution_num, |
1665 | &gstatus.resolution_den); | 1666 | &gstatus.resolution_den); |
@@ -1667,6 +1668,7 @@ static int snd_timer_user_gstatus(struct file *file, | |||
1667 | gstatus.resolution_num = gstatus.resolution; | 1668 | gstatus.resolution_num = gstatus.resolution; |
1668 | gstatus.resolution_den = 1000000000uL; | 1669 | gstatus.resolution_den = 1000000000uL; |
1669 | } | 1670 | } |
1671 | spin_unlock_irq(&t->lock); | ||
1670 | } else { | 1672 | } else { |
1671 | err = -ENODEV; | 1673 | err = -ENODEV; |
1672 | } | 1674 | } |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 9e96186742d0..58fa3f94722a 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -421,13 +421,15 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | |||
421 | kctl->private_free = master_free; | 421 | kctl->private_free = master_free; |
422 | 422 | ||
423 | /* additional (constant) TLV read */ | 423 | /* additional (constant) TLV read */ |
424 | if (tlv && | 424 | if (tlv) { |
425 | (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE || | 425 | unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE]; |
426 | tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX || | 426 | if (type == SNDRV_CTL_TLVT_DB_SCALE || |
427 | tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) { | 427 | type == SNDRV_CTL_TLVT_DB_MINMAX || |
428 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 428 | type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) { |
429 | memcpy(master->tlv, tlv, sizeof(master->tlv)); | 429 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
430 | kctl->tlv.p = master->tlv; | 430 | memcpy(master->tlv, tlv, sizeof(master->tlv)); |
431 | kctl->tlv.p = master->tlv; | ||
432 | } | ||
431 | } | 433 | } |
432 | 434 | ||
433 | return kctl; | 435 | return kctl; |