aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/device.c9
-rw-r--r--sound/core/info.c6
-rw-r--r--sound/core/init.c4
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/pcm.c10
-rw-r--r--sound/core/pcm_compat.c10
-rw-r--r--sound/core/pcm_lib.c15
-rw-r--r--sound/core/pcm_local.h18
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_native.c261
-rw-r--r--sound/core/seq/seq_ports.c2
-rw-r--r--sound/core/seq/seq_timer.c4
-rw-r--r--sound/core/timer.c48
-rw-r--r--sound/core/vmaster.c16
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
706static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr); 706static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
707 707
708static ssize_t 708static ssize_t
709card_number_show_attr(struct device *dev, 709card_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
716static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL); 716static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
717 717
718static struct attribute *card_dev_attrs[] = { 718static 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
1090static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); 1090static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
1091static struct attribute *pcm_dev_attrs[] = { 1091static 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);
36void snd_pcm_playback_silence(struct snd_pcm_substream *substream, 36void 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
39static inline snd_pcm_uframes_t
40snd_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
48static inline snd_pcm_uframes_t
49snd_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
40void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); 58void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
41void snd_pcm_timer_init(struct snd_pcm_substream *substream); 59void 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
106static 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
130static 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 */
110void snd_pcm_stream_lock(struct snd_pcm_substream *substream) 161void 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}
120EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); 165EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
121 166
@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
127 */ 172 */
128void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) 173void 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}
138EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); 177EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
139 178
@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
147 */ 186 */
148void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) 187void 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}
154EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); 191EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
155 192
@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
161 */ 198 */
162void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) 199void 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}
168EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); 203EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
169 204
170unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) 205unsigned 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}
178EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); 209EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
179 210
@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
187void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, 218void 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}
194EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); 223EXPORT_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
889static inline snd_pcm_uframes_t
890snd_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
860int snd_pcm_status(struct snd_pcm_substream *substream, 901int 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
2613static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, 2642static 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
2631static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream, 2659static 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
2649static 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
2667static 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)
2695static int snd_pcm_delay(struct snd_pcm_substream *substream, 2686static 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
3143static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait) 3122static __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
3182static __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}
428EXPORT_SYMBOL(snd_timer_close); 428EXPORT_SYMBOL(snd_timer_close);
429 429
430static 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
430unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) 438unsigned 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}
444EXPORT_SYMBOL(snd_timer_resolution); 454EXPORT_SYMBOL(snd_timer_resolution);
445 455
446static void snd_timer_notify1(struct snd_timer_instance *ti, int event) 456static 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(&register_mutex); 1659 mutex_lock(&register_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;