diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/Kconfig | 4 | ||||
-rw-r--r-- | sound/core/Makefile | 2 | ||||
-rw-r--r-- | sound/core/control.c | 34 | ||||
-rw-r--r-- | sound/core/info.c | 8 | ||||
-rw-r--r-- | sound/core/memalloc.c | 4 | ||||
-rw-r--r-- | sound/core/oss/mixer_oss.c | 3 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 3 | ||||
-rw-r--r-- | sound/core/pcm.c | 26 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 75 | ||||
-rw-r--r-- | sound/core/pcm_memory.c | 2 | ||||
-rw-r--r-- | sound/core/seq/Makefile | 7 |
11 files changed, 94 insertions, 74 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 6061fb5f4e1..c15682a2f9d 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -206,4 +206,8 @@ config SND_PCM_XRUN_DEBUG config SND_VMASTER bool +config SND_DMA_SGBUF + def_bool y + depends on X86 + source "sound/core/seq/Kconfig" diff --git a/sound/core/Makefile b/sound/core/Makefile index 4229052e7b9..350a08d277f 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -13,7 +13,7 @@ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ pcm_memory.o snd-page-alloc-y := memalloc.o -snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o +snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o snd-rawmidi-objs := rawmidi.o snd-timer-objs := timer.o 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) EXPORT_SYMBOL(snd_ctl_remove_id); /** - * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it + * snd_ctl_remove_user_ctl - remove and release the unlocked user control * @file: active control handle * @id: the control id to remove * @@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id); * * Returns 0 if successful, or a negative error code on failure. */ -static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, - struct snd_ctl_elem_id *id) +static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, + struct snd_ctl_elem_id *id) { struct snd_card *card = file->card; struct snd_kcontrol *kctl; @@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, down_write(&card->controls_rwsem); kctl = snd_ctl_find_id(card, id); if (kctl == NULL) { - up_write(&card->controls_rwsem); - return -ENOENT; + ret = -ENOENT; + goto error; + } + if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { + ret = -EINVAL; + goto error; } for (idx = 0; idx < kctl->count; idx++) if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { - up_write(&card->controls_rwsem); - return -EBUSY; + ret = -EBUSY; + goto error; } ret = snd_ctl_remove(card, kctl); + if (ret < 0) + goto error; + card->user_ctl_count--; +error: up_write(&card->controls_rwsem); return ret; } @@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; - if (info->count > 1024) + if (info->count < 1) return -EINVAL; access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| @@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file, struct snd_ctl_elem_id __user *_id) { struct snd_ctl_elem_id id; - int err; if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; - err = snd_ctl_remove_unlocked_id(file, &id); - if (! err) { - struct snd_card *card = file->card; - down_write(&card->controls_rwsem); - card->user_ctl_count--; - up_write(&card->controls_rwsem); - } - return err; + return snd_ctl_remove_user_ctl(file, &id); } 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..d749a0d394a 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, char *nbuf; nsize = PAGE_ALIGN(nsize); - nbuf = kmalloc(nsize, GFP_KERNEL); + nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL); if (! nbuf) return -ENOMEM; - memcpy(nbuf, buffer->buffer, buffer->len); - kfree(buffer->buffer); buffer->buffer = nbuf; buffer->len = nsize; return 0; @@ -108,7 +106,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer, * * Returns the size of output string. */ -int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) +int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...) { va_list args; int len, res; @@ -727,7 +725,7 @@ EXPORT_SYMBOL(snd_info_get_line); * Returns the updated pointer of the original string so that * it can be used for the next call. */ -char *snd_info_get_str(char *dest, char *src, int len) +const char *snd_info_get_str(char *dest, const char *src, int len) { int c; diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 1b3534d6768..9e92441f9b7 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -199,6 +199,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, case SNDRV_DMA_TYPE_DEV: dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); break; +#endif +#ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: snd_malloc_sgbuf_pages(device, size, dmab, NULL); break; @@ -269,6 +271,8 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) case SNDRV_DMA_TYPE_DEV: snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); break; +#endif +#ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: snd_free_sgbuf_pages(dmab); break; diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 5dcd8a52697..772423889eb 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1154,7 +1154,8 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_mixer_oss *mixer = entry->private_data; - char line[128], str[32], idxstr[16], *cptr; + char line[128], str[32], idxstr[16]; + const char *cptr; int ch, idx; struct snd_mixer_oss_assign_table *tbl; struct slot *slot; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index dbe406b8259..d8b2d76125b 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2836,7 +2836,8 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_str *pstr = entry->private_data; - char line[128], str[32], task_name[32], *ptr; + char line[128], str[32], task_name[32]; + const char *ptr; int idx1; struct snd_pcm_oss_setup *setup, *setup1, template; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 145931a9ff3..0c1440121c2 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -162,18 +162,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, return -ENOIOCTLCMD; } -#ifdef CONFIG_SND_VERBOSE_PROCFS - -#define STATE(v) [SNDRV_PCM_STATE_##v] = #v -#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v -#define READY(v) [SNDRV_PCM_READY_##v] = #v -#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v -#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v -#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v -#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v -#define START(v) [SNDRV_PCM_START_##v] = #v #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v -#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v static char *snd_pcm_format_names[] = { FORMAT(S8), @@ -216,10 +205,23 @@ static char *snd_pcm_format_names[] = { FORMAT(U18_3BE), }; -static const char *snd_pcm_format_name(snd_pcm_format_t format) +const char *snd_pcm_format_name(snd_pcm_format_t format) { return snd_pcm_format_names[format]; } +EXPORT_SYMBOL_GPL(snd_pcm_format_name); + +#ifdef CONFIG_SND_VERBOSE_PROCFS + +#define STATE(v) [SNDRV_PCM_STATE_##v] = #v +#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v +#define READY(v) [SNDRV_PCM_READY_##v] = #v +#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v +#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v +#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v +#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v +#define START(v) [SNDRV_PCM_START_##v] = #v +#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v static char *snd_pcm_stream_names[] = { STREAM(PLAYBACK), 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) xrun(substream); return -EPIPE; } + if (xrun_debug(substream, 8)) { + char name[16]; + pcm_debug_name(substream, name, sizeof(name)); + snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, " + "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n", + name, (unsigned int)pos, + (unsigned int)runtime->period_size, + (unsigned int)runtime->buffer_size, + (unsigned long)old_hw_ptr, + (unsigned long)runtime->hw_ptr_base, + (unsigned long)runtime->hw_ptr_interrupt); + } hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; 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) delta = new_hw_ptr - hw_ptr_interrupt; } if (delta < 0) { - delta += runtime->buffer_size; + if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr) + delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value " "(stream=%i, pos=%ld, intr_ptr=%ld)\n", substream->stream, (long)pos, (long)hw_ptr_interrupt); +#if 1 + /* simply skipping the hwptr update seems more + * robust in some cases, e.g. on VMware with + * inaccurate timer source + */ + return 0; /* skip this update */ +#else /* rebase to interrupt position */ hw_base = new_hw_ptr = hw_ptr_interrupt; /* align hw_base to buffer_size */ hw_base -= hw_base % runtime->buffer_size; delta = 0; +#endif } else { hw_base += runtime->buffer_size; if (hw_base >= runtime->boundary) @@ -344,6 +365,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) xrun(substream); return -EPIPE; } + if (xrun_debug(substream, 16)) { + char name[16]; + pcm_debug_name(substream, name, sizeof(name)); + snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, " + "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n", + name, (unsigned int)pos, + (unsigned int)runtime->period_size, + (unsigned int)runtime->buffer_size, + (unsigned long)old_hw_ptr, + (unsigned long)runtime->hw_ptr_base, + (unsigned long)runtime->hw_ptr_interrupt); + } + hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; @@ -909,47 +943,24 @@ static int snd_interval_ratden(struct snd_interval *i, int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) { unsigned int k; - int changed = 0; + struct snd_interval list_range; if (!count) { i->empty = 1; return -EINVAL; } + snd_interval_any(&list_range); + list_range.min = UINT_MAX; + list_range.max = 0; for (k = 0; k < count; k++) { if (mask && !(mask & (1 << k))) continue; - if (i->min == list[k] && !i->openmin) - goto _l1; - if (i->min < list[k]) { - i->min = list[k]; - i->openmin = 0; - changed = 1; - goto _l1; - } - } - i->empty = 1; - return -EINVAL; - _l1: - for (k = count; k-- > 0;) { - if (mask && !(mask & (1 << k))) + if (!snd_interval_test(i, list[k])) continue; - if (i->max == list[k] && !i->openmax) - goto _l2; - if (i->max > list[k]) { - i->max = list[k]; - i->openmax = 0; - changed = 1; - goto _l2; - } + list_range.min = min(list_range.min, list[k]); + list_range.max = max(list_range.max, list[k]); } - i->empty = 1; - return -EINVAL; - _l2: - if (snd_interval_checkempty(i)) { - i->empty = 1; - return -EINVAL; - } - return changed; + return snd_interval_refine(i, &list_range); } EXPORT_SYMBOL(snd_interval_list); diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index a6d42808828..caa7796bc2f 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -304,6 +304,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); +#ifdef CONFIG_SND_DMA_SGBUF /** * snd_pcm_sgbuf_ops_page - get the page struct at the given offset * @substream: the pcm substream instance @@ -349,6 +350,7 @@ unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, return size; } EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); +#endif /* CONFIG_SND_DMA_SGBUF */ /** * snd_pcm_lib_malloc_pages - allocate the DMA buffer 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 @@ # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> # -ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) - obj-$(CONFIG_SND_SEQUENCER) += oss/ -endif - snd-seq-device-objs := seq_device.o snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ seq_fifo.o seq_prioq.o seq_timer.o \ @@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) -obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o + obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o + obj-$(CONFIG_SND_SEQUENCER) += oss/ endif obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o |