diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 34 | ||||
-rw-r--r-- | sound/core/info.c | 4 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 75 | ||||
-rw-r--r-- | sound/core/seq/Makefile | 7 |
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) | |||
414 | EXPORT_SYMBOL(snd_ctl_remove_id); | 414 | EXPORT_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 | */ |
426 | static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, | 426 | static 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--; | ||
452 | error: | ||
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 | ||
1069 | static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) | 1069 | static 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, | |||
909 | int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) | 943 | int 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 | ||
955 | EXPORT_SYMBOL(snd_interval_list); | 966 | EXPORT_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 | ||
6 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | ||
7 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
8 | endif | ||
9 | |||
10 | snd-seq-device-objs := seq_device.o | 6 | snd-seq-device-objs := seq_device.o |
11 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | 7 | snd-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 | ||
20 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o | 16 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o |
21 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 17 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) |
22 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o | 18 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o |
19 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
23 | endif | 20 | endif |
24 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o | 21 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o |
25 | 22 | ||