vserver 2.0 rc7
[linux-2.6.git] / sound / core / oss / mixer_oss.c
index b990156..98ed9a9 100644 (file)
@@ -359,16 +359,9 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
        return -ENXIO;
 }
 
-/* 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)
+static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long 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;
+       return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -384,6 +377,13 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a
        return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+/* all compatible */
+#define snd_mixer_oss_ioctl_compat     snd_mixer_oss_ioctl
+#else
+#define snd_mixer_oss_ioctl_compat     NULL
+#endif
+
 /*
  *  REGISTRATION PART
  */
@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops =
        .owner =        THIS_MODULE,
        .open =         snd_mixer_oss_open,
        .release =      snd_mixer_oss_release,
-       .ioctl =        snd_mixer_oss_ioctl,
+       .unlocked_ioctl =       snd_mixer_oss_ioctl,
+       .compat_ioctl = snd_mixer_oss_ioctl_compat,
 };
 
 static snd_minor_t snd_mixer_oss_reg =
@@ -521,7 +522,7 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
        snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
-       snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+       snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
        *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
        if (uinfo->count > 1)
                *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
@@ -615,7 +616,7 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
-       snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+       snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
        uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
        if (uinfo->count > 1)
                uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
@@ -856,7 +857,7 @@ struct snd_mixer_oss_assign_table {
 
 static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, const char *name, int index, int item)
 {
-       snd_ctl_elem_info_t info;
+       snd_ctl_elem_info_t *info;
        snd_kcontrol_t *kcontrol;
        snd_card_t *card = mixer->card;
        int err;
@@ -867,15 +868,22 @@ static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, c
                up_read(&card->controls_rwsem);
                return 0;
        }
-       if ((err = kcontrol->info(kcontrol, &info)) < 0) {
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (! info) {
+               up_read(&card->controls_rwsem);
+               return -ENOMEM;
+       }
+       if ((err = kcontrol->info(kcontrol, info)) < 0) {
                up_read(&card->controls_rwsem);
+               kfree(info);
                return err;
        }
        slot->numid[item] = kcontrol->id.numid;
        up_read(&card->controls_rwsem);
-       if (info.count > slot->channels)
-               slot->channels = info.count;
+       if (info->count > slot->channels)
+               slot->channels = info->count;
        slot->present |= 1 << item;
+       kfree(info);
        return 0;
 }
 
@@ -960,10 +968,16 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
                return 0;
        down_read(&mixer->card->controls_rwsem);
        if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
-               snd_ctl_elem_info_t uinfo;
+               snd_ctl_elem_info_t *uinfo;
 
-               memset(&uinfo, 0, sizeof(uinfo));
-               if (kctl->info(kctl, &uinfo)) {
+               uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+               if (! uinfo) {
+                       up_read(&mixer->card->controls_rwsem);
+                       return -ENOMEM;
+               }
+                       
+               memset(uinfo, 0, sizeof(*uinfo));
+               if (kctl->info(kctl, uinfo)) {
                        up_read(&mixer->card->controls_rwsem);
                        return 0;
                }
@@ -973,21 +987,22 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
                if (!strcmp(str, "Master Mono"))
                        strcpy(str, "Mix Mono");
                slot.capture_item = 0;
-               if (!strcmp(uinfo.value.enumerated.name, str)) {
+               if (!strcmp(uinfo->value.enumerated.name, str)) {
                        slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
                } else {
-                       for (slot.capture_item = 1; slot.capture_item < uinfo.value.enumerated.items; slot.capture_item++) {
-                               uinfo.value.enumerated.item = slot.capture_item;
-                               if (kctl->info(kctl, &uinfo)) {
+                       for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) {
+                               uinfo->value.enumerated.item = slot.capture_item;
+                               if (kctl->info(kctl, uinfo)) {
                                        up_read(&mixer->card->controls_rwsem);
                                        return 0;
                                }
-                               if (!strcmp(uinfo.value.enumerated.name, str)) {
+                               if (!strcmp(uinfo->value.enumerated.name, str)) {
                                        slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
                                        break;
                                }
                        }
                }
+               kfree(uinfo);
        }
        up_read(&mixer->card->controls_rwsem);
        if (slot.present != 0) {