vserver 1.9.5.x5
[linux-2.6.git] / sound / core / oss / mixer_oss.c
index 8e7efaf..b990156 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -51,7 +52,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        err = snd_card_file_add(card, file);
        if (err < 0)
                return err;
-       fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL);
+       fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
                return -ENOMEM;
@@ -81,7 +82,7 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
 }
 
 static int snd_mixer_oss_info(snd_mixer_oss_file_t *fmixer,
-                             mixer_info *_info)
+                             mixer_info __user *_info)
 {
        snd_card_t *card = fmixer->card;
        snd_mixer_oss_t *mixer = fmixer->mixer;
@@ -97,7 +98,7 @@ static int snd_mixer_oss_info(snd_mixer_oss_file_t *fmixer,
 }
 
 static int snd_mixer_oss_info_obsolete(snd_mixer_oss_file_t *fmixer,
-                                      _old_mixer_info *_info)
+                                      _old_mixer_info __user *_info)
 {
        snd_card_t *card = fmixer->card;
        snd_mixer_oss_t *mixer = fmixer->mixer;
@@ -293,73 +294,81 @@ static int snd_mixer_oss_set_volume(snd_mixer_oss_file_t *fmixer,
 
 static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd, unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
        int tmp;
 
        snd_assert(fmixer != NULL, return -ENXIO);
        if (((cmd >> 8) & 0xff) == 'M') {
                switch (cmd) {
                case SOUND_MIXER_INFO:
-                       return snd_mixer_oss_info(fmixer, (mixer_info *)arg);
+                       return snd_mixer_oss_info(fmixer, argp);
                case SOUND_OLD_MIXER_INFO:
-                       return snd_mixer_oss_info_obsolete(fmixer, (_old_mixer_info *)arg);
+                       return snd_mixer_oss_info_obsolete(fmixer, argp);
                case SOUND_MIXER_WRITE_RECSRC:
-                       if (get_user(tmp, (int *)arg))
+                       if (get_user(tmp, p))
                                return -EFAULT;
                        tmp = snd_mixer_oss_set_recsrc(fmixer, tmp);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                case OSS_GETVERSION:
-                       return put_user(SNDRV_OSS_VERSION, (int *) arg);
+                       return put_user(SNDRV_OSS_VERSION, p);
                case OSS_ALSAEMULVER:
-                       return put_user(1, (int *) arg);
+                       return put_user(1, p);
                case SOUND_MIXER_READ_DEVMASK:
                        tmp = snd_mixer_oss_devmask(fmixer);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                case SOUND_MIXER_READ_STEREODEVS:
                        tmp = snd_mixer_oss_stereodevs(fmixer);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                case SOUND_MIXER_READ_RECMASK:
                        tmp = snd_mixer_oss_recmask(fmixer);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                case SOUND_MIXER_READ_CAPS:
                        tmp = snd_mixer_oss_caps(fmixer);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                case SOUND_MIXER_READ_RECSRC:
                        tmp = snd_mixer_oss_get_recsrc(fmixer);
                        if (tmp < 0)
                                return tmp;
-                       return put_user(tmp, (int *)arg);
+                       return put_user(tmp, p);
                }
        }
        if (cmd & SIOC_IN) {
-               if (get_user(tmp, (int *)arg))
+               if (get_user(tmp, p))
                        return -EFAULT;
                tmp = snd_mixer_oss_set_volume(fmixer, cmd & 0xff, tmp);
                if (tmp < 0)
                        return tmp;
-               return put_user(tmp, (int *)arg);
+               return put_user(tmp, p);
        } else if (cmd & SIOC_OUT) {
                tmp = snd_mixer_oss_get_volume(fmixer, cmd & 0xff);
                if (tmp < 0)
                        return tmp;
-               return put_user(tmp, (int *)arg);
+               return put_user(tmp, p);
        }
        return -ENXIO;
 }
 
-int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
+                              unsigned int cmd, unsigned long arg)
 {
-       return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+       int err;
+       /* FIXME: need to unlock BKL to allow preemption */
+       unlock_kernel();
+       err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+       lock_kernel();
+       return err;
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -506,8 +515,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
                up_read(&card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -518,10 +527,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
                *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
       __unalloc:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
 }
 
 static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
@@ -542,8 +549,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
                up_read(&card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -557,10 +564,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
                *right = 0;
       __unalloc:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
 }
 
 static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
@@ -605,8 +610,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
        down_read(&card->controls_rwsem);
        if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
                return;
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -619,10 +624,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
                snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
       __unalloc:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
 }
 
 static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
@@ -644,8 +647,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
                up_read(&fmixer->card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -664,10 +667,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
                snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
       __unalloc:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
 }
 
 static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
@@ -765,8 +766,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        snd_ctl_elem_value_t *uctl;
        int err, idx;
        
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
                goto __unlock;
@@ -793,10 +794,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        err = 0;
       __unlock:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
        return err;
 }
 
@@ -812,8 +811,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        int err;
        unsigned int idx;
 
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
                goto __unlock;
@@ -844,10 +843,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        err = 0;
       __unlock:
        up_read(&card->controls_rwsem);
-       if (uctl)
-               kfree(uctl);
-       if (uinfo)
-               kfree(uinfo);
+       kfree(uctl);
+       kfree(uinfo);
        return err;
 }
 
@@ -966,8 +963,10 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
                snd_ctl_elem_info_t uinfo;
 
                memset(&uinfo, 0, sizeof(uinfo));
-               if (kctl->info(kctl, &uinfo))
+               if (kctl->info(kctl, &uinfo)) {
+                       up_read(&mixer->card->controls_rwsem);
                        return 0;
+               }
                strcpy(str, ptr->name);
                if (!strcmp(str, "Master"))
                        strcpy(str, "Mix");
@@ -1058,7 +1057,7 @@ static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
 static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
                                    snd_info_buffer_t * buffer)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+       snd_mixer_oss_t *mixer = entry->private_data;
        int i;
 
        down(&mixer->reg_mutex);
@@ -1082,7 +1081,7 @@ static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
 static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
                                     snd_info_buffer_t * buffer)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+       snd_mixer_oss_t *mixer = entry->private_data;
        char line[128], str[32], idxstr[16], *cptr;
        int ch, idx;
        struct snd_mixer_oss_assign_table *tbl;
@@ -1208,7 +1207,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
        };
        unsigned int idx;
        
-       for (idx = 0; idx < sizeof(table) / sizeof(struct snd_mixer_oss_assign_table); idx++)
+       for (idx = 0; idx < ARRAY_SIZE(table); idx++)
                snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
        if (mixer->mask_recsrc) {
                mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
@@ -1222,7 +1221,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
 
 static int snd_mixer_oss_free1(void *private)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, private, return -ENXIO);
+       snd_mixer_oss_t *mixer = private;
        snd_card_t * card;
        int idx;
  
@@ -1235,7 +1234,7 @@ static int snd_mixer_oss_free1(void *private)
                if (chn->private_free)
                        chn->private_free(chn);
        }
-       snd_magic_kfree(mixer);
+       kfree(mixer);
        return 0;
 }
 
@@ -1247,7 +1246,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
                char name[128];
                int idx, err;
 
-               mixer = snd_magic_kcalloc(snd_mixer_oss_t, sizeof(snd_mixer_oss_t), GFP_KERNEL);
+               mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
                if (mixer == NULL)
                        return -ENOMEM;
                init_MUTEX(&mixer->reg_mutex);
@@ -1257,7 +1256,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
                                                   &snd_mixer_oss_reg,
                                                   name)) < 0) {
                        snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0);
-                       snd_magic_kfree(mixer);
+                       kfree(mixer);
                        return err;
                }
                mixer->oss_dev_alloc = 1;