diff options
Diffstat (limited to 'sound/core')
39 files changed, 178 insertions, 32 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index f8c5be46451..819a5c579a3 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -21,6 +21,7 @@ #include <linux/threads.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/time.h> @@ -989,7 +990,6 @@ struct user_element { void *tlv_data; /* TLV data */ unsigned long tlv_data_size; /* TLV data size */ void *priv_data; /* private data (like strings for enumerated type) */ - unsigned long priv_data_size; /* size of private data in bytes */ }; static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, @@ -1001,6 +1001,28 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, return 0; } +static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct user_element *ue = kcontrol->private_data; + const char *names; + unsigned int item; + + item = uinfo->value.enumerated.item; + + *uinfo = ue->info; + + item = min(item, uinfo->value.enumerated.items - 1); + uinfo->value.enumerated.item = item; + + names = ue->priv_data; + for (; item > 0; --item) + names += strlen(names) + 1; + strcpy(uinfo->value.enumerated.name, names); + + return 0; +} + static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1055,11 +1077,46 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, return change; } +static int snd_ctl_elem_init_enum_names(struct user_element *ue) +{ + char *names, *p; + size_t buf_len, name_len; + unsigned int i; + const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr; + + if (ue->info.value.enumerated.names_length > 64 * 1024) + return -EINVAL; + + names = memdup_user((const void __user *)user_ptrval, + ue->info.value.enumerated.names_length); + if (IS_ERR(names)) + return PTR_ERR(names); + + /* check that there are enough valid names */ + buf_len = ue->info.value.enumerated.names_length; + p = names; + for (i = 0; i < ue->info.value.enumerated.items; ++i) { + name_len = strnlen(p, buf_len); + if (name_len == 0 || name_len >= 64 || name_len == buf_len) { + kfree(names); + return -EINVAL; + } + p += name_len + 1; + buf_len -= name_len + 1; + } + + ue->priv_data = names; + ue->info.value.enumerated.names_ptr = 0; + + return 0; +} + static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) { struct user_element *ue = kcontrol->private_data; - if (ue->tlv_data) - kfree(ue->tlv_data); + + kfree(ue->tlv_data); + kfree(ue->priv_data); kfree(ue); } @@ -1072,8 +1129,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, long private_size; struct user_element *ue; int idx, err; - - if (card->user_ctl_count >= MAX_USER_CONTROLS) + + if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; if (info->count < 1) return -EINVAL; @@ -1101,7 +1158,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, memcpy(&kctl.id, &info->id, sizeof(info->id)); kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; - kctl.info = snd_ctl_elem_user_info; + if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) + kctl.info = snd_ctl_elem_user_enum_info; + else + kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) @@ -1122,6 +1182,11 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (info->count > 64) return -EINVAL; break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + private_size = sizeof(unsigned int); + if (info->count > 128 || info->value.enumerated.items == 0) + return -EINVAL; + break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); if (info->count > 512) @@ -1143,9 +1208,17 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, ue->info.access = 0; ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; + if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { + err = snd_ctl_elem_init_enum_names(ue); + if (err < 0) { + kfree(ue); + return err; + } + } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { + kfree(ue->priv_data); kfree(ue); return -ENOMEM; } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 426874429a5..2bb95a7a880 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -83,6 +83,8 @@ struct snd_ctl_elem_info32 { u32 items; u32 item; char name[64]; + u64 names_ptr; + u32 names_length; } enumerated; unsigned char reserved[128]; } value; @@ -372,6 +374,8 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, &data32->value.enumerated, sizeof(data->value.enumerated))) goto error; + data->value.enumerated.names_ptr = + (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); break; default: break; diff --git a/sound/core/device.c b/sound/core/device.c index 2d1ad4b0cd6..f03cb5444a5 100644 --- a/sound/core/device.c +++ b/sound/core/device.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/time.h> +#include <linux/export.h> #include <linux/errno.h> #include <sound/core.h> diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index a70ee7f1ed9..75ea16f35b1 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/mutex.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/control.h> #include <sound/minors.h> @@ -272,7 +273,14 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; + + if (device < 0) + device = 0; + else if (device < SNDRV_MINOR_HWDEPS) + device++; + else + device = SNDRV_MINOR_HWDEPS; + while (device < SNDRV_MINOR_HWDEPS) { if (snd_hwdep_search(card, device)) break; diff --git a/sound/core/info.c b/sound/core/info.c index 601f0ebb677..c1e611c65c8 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -24,6 +24,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/minors.h> #include <sound/info.h> diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index e4af138d651..cf42ab5080e 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/string.h> +#include <linux/export.h> #include <sound/core.h> #include <sound/minors.h> #include <sound/info.h> diff --git a/sound/core/init.c b/sound/core/init.c index 2c041bb36ab..3ac49b1b7cb 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/sched.h> +#include <linux/module.h> #include <linux/file.h> #include <linux/slab.h> #include <linux/time.h> diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 950e19ba91f..c0f1208bb7d 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c @@ -26,6 +26,7 @@ #undef HAVE_REALLY_SLOW_DMA_CONTROLLER +#include <linux/export.h> #include <sound/core.h> #include <asm/dma.h> diff --git a/sound/core/jack.c b/sound/core/jack.c index 53b53e97c89..26edf63b265 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -21,6 +21,7 @@ #include <linux/input.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/jack.h> #include <sound/core.h> @@ -30,6 +31,7 @@ static int jack_switch_types[] = { SW_LINEOUT_INSERT, SW_JACK_PHYSICAL_INSERT, SW_VIDEOOUT_INSERT, + SW_LINEIN_INSERT, }; static int snd_jack_dev_free(struct snd_device *device) diff --git a/sound/core/memory.c b/sound/core/memory.c index 1161158582a..66a278d0b04 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -20,6 +20,7 @@ * */ +#include <linux/export.h> #include <asm/io.h> #include <asm/uaccess.h> #include <sound/core.h> diff --git a/sound/core/misc.c b/sound/core/misc.c index eb9fe2e1d29..465f0ce772c 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -20,6 +20,8 @@ */ #include <linux/init.h> +#include <linux/export.h> +#include <linux/moduleparam.h> #include <linux/time.h> #include <linux/slab.h> #include <linux/ioport.h> diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index d8359cfeca1..18297f7f2c5 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/string.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/minors.h> #include <sound/control.h> @@ -499,7 +500,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, name); + strlcpy(id.name, name, sizeof(id.name)); id.index = index; return snd_ctl_find_id(card, &id); } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 23c34a02894..3cc4b86dfb7 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -30,7 +30,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/vmalloc.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/math64.h> #include <linux/string.h> #include <sound/core.h> diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ee9abb2d900..8928ca871c2 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/slab.h> +#include <linux/module.h> #include <linux/time.h> #include <linux/mutex.h> #include <sound/core.h> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 62e90b862a0..3420bd3da5d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/math64.h> +#include <linux/export.h> #include <sound/core.h> #include <sound/control.h> #include <sound/info.h> @@ -1399,6 +1400,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); +static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + unsigned int base_rate = (unsigned int)(uintptr_t)rule->private; + struct snd_interval *rate; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + return snd_interval_list(rate, 1, &base_rate, 0); +} + +/** + * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling + * @runtime: PCM runtime instance + * @base_rate: the rate at which the hardware does not resample + */ +int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime, + unsigned int base_rate) +{ + return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE, + SNDRV_PCM_HW_PARAM_RATE, + snd_pcm_hw_rule_noresample_func, + (void *)(uintptr_t)base_rate, + SNDRV_PCM_HW_PARAM_RATE, -1); +} +EXPORT_SYMBOL(snd_pcm_hw_rule_noresample); + static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) { diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 150cb7edffe..957131366dd 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -25,6 +25,7 @@ #include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/vmalloc.h> +#include <linux/export.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/info.h> diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 88f02e3866e..9c9eff9afba 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -20,6 +20,7 @@ */ #include <linux/time.h> +#include <linux/export.h> #include <sound/core.h> #include <sound/pcm.h> #define SND_PCM_FORMAT_UNKNOWN (-1) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c74e228731e..25ed9fe41b8 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -20,6 +20,7 @@ */ #include <linux/mm.h> +#include <linux/module.h> #include <linux/file.h> #include <linux/slab.h> #include <linux/time.h> @@ -2058,16 +2059,12 @@ EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, - int stream, - struct snd_pcm_file **rpcm_file) + int stream) { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; int err; - if (rpcm_file) - *rpcm_file = NULL; - err = snd_pcm_open_substream(pcm, stream, file, &substream); if (err < 0) return err; @@ -2083,8 +2080,7 @@ static int snd_pcm_open_file(struct file *file, substream->pcm_release = pcm_release_private; } file->private_data = pcm_file; - if (rpcm_file) - *rpcm_file = pcm_file; + return 0; } @@ -2113,7 +2109,6 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) { int err; - struct snd_pcm_file *pcm_file; wait_queue_t wait; if (pcm == NULL) { @@ -2131,7 +2126,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) add_wait_queue(&pcm->open_wait, &wait); mutex_lock(&pcm->open_mutex); while (1) { - err = snd_pcm_open_file(file, pcm, stream, &pcm_file); + err = snd_pcm_open_file(file, pcm, stream); if (err >= 0) break; if (err == -EAGAIN) { @@ -3156,8 +3151,8 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { /* * mmap the DMA buffer on RAM */ -static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *area) +int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *area) { area->vm_flags |= VM_RESERVED; #ifdef ARCH_HAS_DMA_MMAP_COHERENT @@ -3177,6 +3172,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; } +EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); /* * mmap the DMA buffer on I/O memory area @@ -3242,7 +3238,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, if (substream->ops->mmap) err = substream->ops->mmap(substream, area); else - err = snd_pcm_default_mmap(substream, area); + err = snd_pcm_lib_default_mmap(substream, area); if (!err) atomic_inc(&substream->mmap_count); return err; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 849a0ed9505..ebf6e49ad3d 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -27,7 +27,7 @@ #include <linux/time.h> #include <linux/wait.h> #include <linux/mutex.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/delay.h> #include <sound/rawmidi.h> #include <sound/info.h> diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index a1f1a2f00cc..8d4d5e853ef 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -21,7 +21,7 @@ */ #include <linux/init.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/mutex.h> #include <sound/core.h> #include <sound/minors.h> diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 69cd7b3c362..e3cb46fef2c 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -28,6 +28,7 @@ #include "seq_oss_timer.h" #include "seq_oss_event.h" #include <linux/init.h> +#include <linux/export.h> #include <linux/moduleparam.h> #include <linux/slab.h> diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index ee44ab9593c..c5b773a1eea 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -24,6 +24,7 @@ #include "seq_oss_midi.h" #include "../seq_lock.h" #include <linux/init.h> +#include <linux/module.h> #include <linux/slab.h> /* diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 119fddb6fc9..9d8379aedf4 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -20,7 +20,7 @@ */ #include <linux/init.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index f2436d33fbf..4dc6bae80e1 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -22,6 +22,7 @@ */ #include <linux/init.h> +#include <linux/export.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/minors.h> diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 1f997675c89..5cf8d65ed5e 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -37,6 +37,7 @@ */ #include <linux/init.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/info.h> #include <sound/seq_device.h> diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 1d7d90ca455..b9b2235d9ab 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -20,7 +20,7 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <sound/core.h> #include "seq_clientmgr.h" #include <sound/initval.h> diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index 201f8106ffd..acf7769419f 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c @@ -20,6 +20,7 @@ */ #include <linux/init.h> +#include <linux/export.h> #include <sound/core.h> #include "seq_info.h" diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 54f921edda7..2cfe50c71a9 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -19,6 +19,7 @@ * */ +#include <linux/export.h> #include <sound/core.h> #include "seq_lock.h" diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 7f50c143767..f478f770bf5 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -21,6 +21,7 @@ */ #include <linux/init.h> +#include <linux/export.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <sound/core.h> diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index ebaf1b541dc..64069dbf89c 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -30,7 +30,7 @@ Possible options for midisynth module: #include <linux/slab.h> #include <linux/errno.h> #include <linux/string.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/mutex.h> #include <sound/core.h> #include <sound/rawmidi.h> diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 07c663135c6..6f64471ddde 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -32,6 +32,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/seq_kernel.h> #include <sound/seq_midi_emul.h> diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index b5d6ea4904c..37db7ba492a 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/seq_kernel.h> #include <sound/seq_midi_event.h> diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index e12bcd94b6d..9516e5ce3aa 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -22,6 +22,7 @@ #include <sound/core.h> #include <linux/slab.h> +#include <linux/module.h> #include "seq_system.h" #include "seq_ports.h" #include "seq_clientmgr.h" diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c index c38b90cf3cb..8ce1d0b40dc 100644 --- a/sound/core/seq/seq_system.c +++ b/sound/core/seq/seq_system.c @@ -20,6 +20,7 @@ */ #include <linux/init.h> +#include <linux/export.h> #include <linux/slab.h> #include <sound/core.h> #include "seq_system.h" diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 86e7739269c..4b50e604276 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -37,6 +37,7 @@ #include <linux/init.h> #include <linux/wait.h> +#include <linux/module.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/rawmidi.h> diff --git a/sound/core/sound.c b/sound/core/sound.c index 1c7a3efe177..828af353ea9 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -23,7 +23,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/device.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/minors.h> #include <sound/info.h> diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 0c164e5e432..c7009204306 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -26,6 +26,7 @@ #endif #include <linux/init.h> +#include <linux/export.h> #include <linux/slab.h> #include <linux/time.h> #include <sound/core.h> diff --git a/sound/core/timer.c b/sound/core/timer.c index 67ebf1c21c0..8e7561dfc5f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -24,7 +24,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/mutex.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/string.h> #include <sound/core.h> #include <sound/timer.h> diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index a39d3d8c2f9..130cfe677d6 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -10,6 +10,7 @@ */ #include <linux/slab.h> +#include <linux/export.h> #include <sound/core.h> #include <sound/control.h> #include <sound/tlv.h> @@ -51,6 +52,7 @@ struct link_slave { struct link_ctl_info info; int vals[2]; /* current values */ unsigned int flags; + struct snd_kcontrol *kctl; /* original kcontrol pointer */ struct snd_kcontrol slave; /* the copy of original control entry */ }; @@ -251,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, slave->count * sizeof(*slave->vd), GFP_KERNEL); if (!srec) return -ENOMEM; + srec->kctl = slave; srec->slave = *slave; memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); srec->master = master_link; @@ -332,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol, static void master_free(struct snd_kcontrol *kcontrol) { struct link_master *master = snd_kcontrol_chip(kcontrol); - struct link_slave *slave; - - list_for_each_entry(slave, &master->slaves, list) - slave->master = NULL; + struct link_slave *slave, *n; + + /* free all slave links and retore the original slave kctls */ + list_for_each_entry_safe(slave, n, &master->slaves, list) { + struct snd_kcontrol *sctl = slave->kctl; + struct list_head olist = sctl->list; + memcpy(sctl, &slave->slave, sizeof(*sctl)); + memcpy(sctl->vd, slave->slave.vd, + sctl->count * sizeof(*sctl->vd)); + sctl->list = olist; /* keep the current linked-list */ + kfree(slave); + } kfree(master); } |