aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/control.c34
-rw-r--r--sound/core/info.c4
-rw-r--r--sound/core/pcm_lib.c75
-rw-r--r--sound/core/seq/Makefile7
4 files changed, 63 insertions, 57 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 17b8d47a5cd..a8b7fabe645 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -414,7 +414,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
414EXPORT_SYMBOL(snd_ctl_remove_id); 414EXPORT_SYMBOL(snd_ctl_remove_id);
415 415
416/** 416/**
417 * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it 417 * snd_ctl_remove_user_ctl - remove and release the unlocked user control
418 * @file: active control handle 418 * @file: active control handle
419 * @id: the control id to remove 419 * @id: the control id to remove
420 * 420 *
@@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
423 * 423 *
424 * Returns 0 if successful, or a negative error code on failure. 424 * Returns 0 if successful, or a negative error code on failure.
425 */ 425 */
426static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, 426static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
427 struct snd_ctl_elem_id *id) 427 struct snd_ctl_elem_id *id)
428{ 428{
429 struct snd_card *card = file->card; 429 struct snd_card *card = file->card;
430 struct snd_kcontrol *kctl; 430 struct snd_kcontrol *kctl;
@@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
433 down_write(&card->controls_rwsem); 433 down_write(&card->controls_rwsem);
434 kctl = snd_ctl_find_id(card, id); 434 kctl = snd_ctl_find_id(card, id);
435 if (kctl == NULL) { 435 if (kctl == NULL) {
436 up_write(&card->controls_rwsem); 436 ret = -ENOENT;
437 return -ENOENT; 437 goto error;
438 }
439 if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
440 ret = -EINVAL;
441 goto error;
438 } 442 }
439 for (idx = 0; idx < kctl->count; idx++) 443 for (idx = 0; idx < kctl->count; idx++)
440 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { 444 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
441 up_write(&card->controls_rwsem); 445 ret = -EBUSY;
442 return -EBUSY; 446 goto error;
443 } 447 }
444 ret = snd_ctl_remove(card, kctl); 448 ret = snd_ctl_remove(card, kctl);
449 if (ret < 0)
450 goto error;
451 card->user_ctl_count--;
452error:
445 up_write(&card->controls_rwsem); 453 up_write(&card->controls_rwsem);
446 return ret; 454 return ret;
447} 455}
@@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
951 959
952 if (card->user_ctl_count >= MAX_USER_CONTROLS) 960 if (card->user_ctl_count >= MAX_USER_CONTROLS)
953 return -ENOMEM; 961 return -ENOMEM;
954 if (info->count > 1024) 962 if (info->count < 1)
955 return -EINVAL; 963 return -EINVAL;
956 access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : 964 access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
957 (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| 965 (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
@@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file,
1052 struct snd_ctl_elem_id __user *_id) 1060 struct snd_ctl_elem_id __user *_id)
1053{ 1061{
1054 struct snd_ctl_elem_id id; 1062 struct snd_ctl_elem_id id;
1055 int err;
1056 1063
1057 if (copy_from_user(&id, _id, sizeof(id))) 1064 if (copy_from_user(&id, _id, sizeof(id)))
1058 return -EFAULT; 1065 return -EFAULT;
1059 err = snd_ctl_remove_unlocked_id(file, &id); 1066 return snd_ctl_remove_user_ctl(file, &id);
1060 if (! err) {
1061 struct snd_card *card = file->card;
1062 down_write(&card->controls_rwsem);
1063 card->user_ctl_count--;
1064 up_write(&card->controls_rwsem);
1065 }
1066 return err;
1067} 1067}
1068 1068
1069static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) 1069static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
diff --git a/sound/core/info.c b/sound/core/info.c
index 35df614f6c5..3d1f5137420 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -88,12 +88,10 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
88 char *nbuf; 88 char *nbuf;
89 89
90 nsize = PAGE_ALIGN(nsize); 90 nsize = PAGE_ALIGN(nsize);
91 nbuf = kmalloc(nsize, GFP_KERNEL); 91 nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
92 if (! nbuf) 92 if (! nbuf)
93 return -ENOMEM; 93 return -ENOMEM;
94 94
95 memcpy(nbuf, buffer->buffer, buffer->len);
96 kfree(buffer->buffer);
97 buffer->buffer = nbuf; 95 buffer->buffer = nbuf;
98 buffer->len = nsize; 96 buffer->len = nsize;
99 return 0; 97 return 0;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 333e4dd2945..9db60d831bb 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -233,6 +233,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
233 xrun(substream); 233 xrun(substream);
234 return -EPIPE; 234 return -EPIPE;
235 } 235 }
236 if (xrun_debug(substream, 8)) {
237 char name[16];
238 pcm_debug_name(substream, name, sizeof(name));
239 snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
240 "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
241 name, (unsigned int)pos,
242 (unsigned int)runtime->period_size,
243 (unsigned int)runtime->buffer_size,
244 (unsigned long)old_hw_ptr,
245 (unsigned long)runtime->hw_ptr_base,
246 (unsigned long)runtime->hw_ptr_interrupt);
247 }
236 hw_base = runtime->hw_ptr_base; 248 hw_base = runtime->hw_ptr_base;
237 new_hw_ptr = hw_base + pos; 249 new_hw_ptr = hw_base + pos;
238 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; 250 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
@@ -244,18 +256,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
244 delta = new_hw_ptr - hw_ptr_interrupt; 256 delta = new_hw_ptr - hw_ptr_interrupt;
245 } 257 }
246 if (delta < 0) { 258 if (delta < 0) {
247 delta += runtime->buffer_size; 259 if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
260 delta += runtime->buffer_size;
248 if (delta < 0) { 261 if (delta < 0) {
249 hw_ptr_error(substream, 262 hw_ptr_error(substream,
250 "Unexpected hw_pointer value " 263 "Unexpected hw_pointer value "
251 "(stream=%i, pos=%ld, intr_ptr=%ld)\n", 264 "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
252 substream->stream, (long)pos, 265 substream->stream, (long)pos,
253 (long)hw_ptr_interrupt); 266 (long)hw_ptr_interrupt);
267#if 1
268 /* simply skipping the hwptr update seems more
269 * robust in some cases, e.g. on VMware with
270 * inaccurate timer source
271 */
272 return 0; /* skip this update */
273#else
254 /* rebase to interrupt position */ 274 /* rebase to interrupt position */
255 hw_base = new_hw_ptr = hw_ptr_interrupt; 275 hw_base = new_hw_ptr = hw_ptr_interrupt;
256 /* align hw_base to buffer_size */ 276 /* align hw_base to buffer_size */
257 hw_base -= hw_base % runtime->buffer_size; 277 hw_base -= hw_base % runtime->buffer_size;
258 delta = 0; 278 delta = 0;
279#endif
259 } else { 280 } else {
260 hw_base += runtime->buffer_size; 281 hw_base += runtime->buffer_size;
261 if (hw_base >= runtime->boundary) 282 if (hw_base >= runtime->boundary)
@@ -344,6 +365,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
344 xrun(substream); 365 xrun(substream);
345 return -EPIPE; 366 return -EPIPE;
346 } 367 }
368 if (xrun_debug(substream, 16)) {
369 char name[16];
370 pcm_debug_name(substream, name, sizeof(name));
371 snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
372 "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
373 name, (unsigned int)pos,
374 (unsigned int)runtime->period_size,
375 (unsigned int)runtime->buffer_size,
376 (unsigned long)old_hw_ptr,
377 (unsigned long)runtime->hw_ptr_base,
378 (unsigned long)runtime->hw_ptr_interrupt);
379 }
380
347 hw_base = runtime->hw_ptr_base; 381 hw_base = runtime->hw_ptr_base;
348 new_hw_ptr = hw_base + pos; 382 new_hw_ptr = hw_base + pos;
349 383
@@ -909,47 +943,24 @@ static int snd_interval_ratden(struct snd_interval *i,
909int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) 943int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
910{ 944{
911 unsigned int k; 945 unsigned int k;
912 int changed = 0; 946 struct snd_interval list_range;
913 947
914 if (!count) { 948 if (!count) {
915 i->empty = 1; 949 i->empty = 1;
916 return -EINVAL; 950 return -EINVAL;
917 } 951 }
952 snd_interval_any(&list_range);
953 list_range.min = UINT_MAX;
954 list_range.max = 0;
918 for (k = 0; k < count; k++) { 955 for (k = 0; k < count; k++) {
919 if (mask && !(mask & (1 << k))) 956 if (mask && !(mask & (1 << k)))
920 continue; 957 continue;
921 if (i->min == list[k] && !i->openmin) 958 if (!snd_interval_test(i, list[k]))
922 goto _l1;
923 if (i->min < list[k]) {
924 i->min = list[k];
925 i->openmin = 0;
926 changed = 1;
927 goto _l1;
928 }
929 }
930 i->empty = 1;
931 return -EINVAL;
932 _l1:
933 for (k = count; k-- > 0;) {
934 if (mask && !(mask & (1 << k)))
935 continue; 959 continue;
936 if (i->max == list[k] && !i->openmax) 960 list_range.min = min(list_range.min, list[k]);
937 goto _l2; 961 list_range.max = max(list_range.max, list[k]);
938 if (i->max > list[k]) {
939 i->max = list[k];
940 i->openmax = 0;
941 changed = 1;
942 goto _l2;
943 }
944 } 962 }
945 i->empty = 1; 963 return snd_interval_refine(i, &list_range);
946 return -EINVAL;
947 _l2:
948 if (snd_interval_checkempty(i)) {
949 i->empty = 1;
950 return -EINVAL;
951 }
952 return changed;
953} 964}
954 965
955EXPORT_SYMBOL(snd_interval_list); 966EXPORT_SYMBOL(snd_interval_list);
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index 1bcb360330e..941f64a853e 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -3,10 +3,6 @@
3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> 3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4# 4#
5 5
6ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
7 obj-$(CONFIG_SND_SEQUENCER) += oss/
8endif
9
10snd-seq-device-objs := seq_device.o 6snd-seq-device-objs := seq_device.o
11snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ 7snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
12 seq_fifo.o seq_prioq.o seq_timer.o \ 8 seq_fifo.o seq_prioq.o seq_timer.o \
@@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o
19 15
20obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o 16obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
21ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) 17ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
22obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o 18 obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
19 obj-$(CONFIG_SND_SEQUENCER) += oss/
23endif 20endif
24obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o 21obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
25 22