Merge branch 'for_paulus' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc
[pandora-kernel.git] / sound / core / oss / pcm_oss.c
index 2ae283c..c5978d6 100644 (file)
@@ -78,6 +78,7 @@ static inline void snd_leave_user(mm_segment_t fs)
        set_fs(fs);
 }
 
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
 static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -122,6 +123,7 @@ int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
        }
        return 0;
 }
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
 
 static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
 {
@@ -206,9 +208,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
                        oss_buffer_size = runtime->oss.mmap_bytes;
        }
 
-       if (substream->oss.setup &&
-           substream->oss.setup->period_size > 16)
-               oss_period_size = substream->oss.setup->period_size;
+       if (substream->oss.setup.period_size > 16)
+               oss_period_size = substream->oss.setup.period_size;
        else if (runtime->oss.fragshift) {
                oss_period_size = 1 << runtime->oss.fragshift;
                if (oss_period_size > oss_buffer_size / 2)
@@ -250,10 +251,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
 
        oss_periods = oss_buffer_size / oss_period_size;
 
-       if (substream->oss.setup) {
-               if (substream->oss.setup->periods > 1)
-                       oss_periods = substream->oss.setup->periods;
-       }
+       if (substream->oss.setup.periods > 1)
+               oss_periods = substream->oss.setup.periods;
 
        s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
        if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
@@ -339,12 +338,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
                goto failure;
        }
 
-       if (atomic_read(&runtime->mmap_count)) {
+       if (atomic_read(&runtime->mmap_count))
                direct = 1;
-       } else {
-               struct snd_pcm_oss_setup *setup = substream->oss.setup;
-               direct = (setup != NULL && setup->direct);
-       }
+       else
+               direct = substream->oss.setup.direct;
 
        _snd_pcm_hw_params_any(sparams);
        _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
@@ -412,6 +409,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
        oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
                         params_channels(params) / 8;
 
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
        snd_pcm_oss_plugin_clear(substream);
        if (!direct) {
                /* add necessary plugins */
@@ -441,6 +439,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
                        }
                }
        }
+#endif
 
        err = snd_pcm_oss_period_size(substream, params, sparams);
        if (err < 0)
@@ -478,7 +477,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
                1 : runtime->period_size;
        sw_params->xfer_align = 1;
        if (atomic_read(&runtime->mmap_count) ||
-           (substream->oss.setup && substream->oss.setup->nosilence)) {
+           substream->oss.setup.nosilence) {
                sw_params->silence_threshold = 0;
                sw_params->silence_size = 0;
        } else {
@@ -498,11 +497,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
        runtime->oss.periods = params_periods(sparams);
        oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
        snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
        if (runtime->oss.plugin_first) {
                err = snd_pcm_plug_alloc(substream, oss_period_size);
                if (err < 0)
                        goto failure;
        }
+#endif
        oss_period_size *= oss_frame_size;
 
        oss_buffer_size = oss_period_size * runtime->oss.periods;
@@ -784,6 +785,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
        if (runtime->oss.plugin_first) {
                struct snd_pcm_plugin_channel *channels;
                size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
@@ -800,7 +802,9 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
                if (frames1 <= 0)
                        return frames1;
                bytes = frames1 * oss_frame_bytes;
-       } else {
+       } else
+#endif
+       {
                frames = bytes_to_frames(runtime, bytes);
                frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
                if (frames1 <= 0)
@@ -834,7 +838,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
                        buf += tmp;
                        bytes -= tmp;
                        xfer += tmp;
-                       if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
+                       if (substream->oss.setup.partialfrag ||
                            runtime->oss.buffer_used == runtime->oss.period_bytes) {
                                tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 
                                                         runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
@@ -871,6 +875,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
        char __user *final_dst = (char __user *)buf;
        if (runtime->oss.plugin_first) {
                struct snd_pcm_plugin_channel *channels;
@@ -887,7 +892,9 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
                bytes = frames1 * oss_frame_bytes;
                if (!in_kernel && copy_to_user(final_dst, buf, bytes))
                        return -EFAULT;
-       } else {
+       } else
+#endif
+       {
                frames = bytes_to_frames(runtime, bytes);
                frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
                if (frames1 <= 0)
@@ -947,12 +954,12 @@ static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
 
        substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
        if (substream != NULL) {
-               snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+               snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
                substream->runtime->oss.prepare = 1;
        }
        substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
        if (substream != NULL) {
-               snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+               snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
                substream->runtime->oss.prepare = 1;
        }
        return 0;
@@ -967,7 +974,7 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
        if (substream != NULL) {
                if ((err = snd_pcm_oss_make_ready(substream)) < 0)
                        return err;
-               snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
+               snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
        }
        /* note: all errors from the start action are ignored */
        /* OSS apps do not know, how to handle them */
@@ -1096,7 +1103,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
              __direct:
                saved_f_flags = substream->ffile->f_flags;
                substream->ffile->f_flags &= ~O_NONBLOCK;
-               err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
+               err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
                substream->ffile->f_flags = saved_f_flags;
                if (err < 0)
                        return err;
@@ -1108,7 +1115,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
                if ((err = snd_pcm_oss_make_ready(substream)) < 0)
                        return err;
                runtime = substream->runtime;
-               err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+               err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
                if (err < 0)
                        return err;
                runtime->oss.buffer_used = 0;
@@ -1202,12 +1209,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
 
        if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
                return err;
-       if (atomic_read(&substream->runtime->mmap_count)) {
+       if (atomic_read(&substream->runtime->mmap_count))
                direct = 1;
-       } else {
-               struct snd_pcm_oss_setup *setup = substream->oss.setup;
-               direct = (setup != NULL && setup->direct);
-       }
+       else
+               direct = substream->oss.setup.direct;
        if (!direct)
                return AFMT_MU_LAW | AFMT_U8 |
                       AFMT_S16_LE | AFMT_S16_BE |
@@ -1425,7 +1430,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
                        cmd = SNDRV_PCM_IOCTL_DROP;
                        runtime->oss.prepare = 1;
                }
-               err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL);
+               err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
                if (err < 0)
                        return err;
        }
@@ -1446,7 +1451,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
                        cmd = SNDRV_PCM_IOCTL_DROP;
                        runtime->oss.prepare = 1;
                }
-               err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL);
+               err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
                if (err < 0)
                        return err;
        }
@@ -1483,7 +1488,7 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
        runtime = substream->runtime;
        if (runtime->oss.params || runtime->oss.prepare)
                return 0;
-       err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+       err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
        if (err == -EPIPE)
                delay = 0;      /* hack for broken OSS applications */
        else if (err < 0)
@@ -1543,8 +1548,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
        } else {
                delay = snd_pcm_oss_bytes(substream, delay);
                if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       struct snd_pcm_oss_setup *setup = substream->oss.setup;
-                       if (setup && setup->buggyptr)
+                       if (substream->oss.setup.buggyptr)
                                info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
                        else
                                info.blocks = (delay + fixup) / runtime->oss.period_bytes;
@@ -1626,37 +1630,46 @@ static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int str
        return -EINVAL;
 }
 
-static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
+static const char *strip_task_path(const char *path)
 {
-       const char *ptr, *ptrl;
-       struct snd_pcm_oss_setup *setup;
-
-       down(&pcm->streams[stream].oss.setup_mutex);
-       for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
-               if (!strcmp(setup->task_name, task_name)) {
-                       up(&pcm->streams[stream].oss.setup_mutex);
-                       return setup;
-               }
-       }
-       ptr = ptrl = task_name;
-       while (*ptr) {
+       const char *ptr, *ptrl = NULL;
+       for (ptr = path; *ptr; ptr++) {
                if (*ptr == '/')
                        ptrl = ptr + 1;
-               ptr++;
        }
-       if (ptrl == task_name) {
-               goto __not_found;
-               return NULL;
-       }
-       for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
-               if (!strcmp(setup->task_name, ptrl)) {
-                       up(&pcm->streams[stream].oss.setup_mutex);
-                       return setup;
+       return ptrl;
+}
+
+static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
+                                     const char *task_name,
+                                     struct snd_pcm_oss_setup *rsetup)
+{
+       struct snd_pcm_oss_setup *setup;
+
+       mutex_lock(&pcm->streams[stream].oss.setup_mutex);
+       do {
+               for (setup = pcm->streams[stream].oss.setup_list; setup;
+                    setup = setup->next) {
+                       if (!strcmp(setup->task_name, task_name))
+                               goto out;
                }
-       }
-      __not_found:
-       up(&pcm->streams[stream].oss.setup_mutex);
-       return NULL;
+       } while ((task_name = strip_task_path(task_name)) != NULL);
+ out:
+       if (setup)
+               *rsetup = *setup;
+       mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
+}
+
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime;
+       runtime = substream->runtime;
+       vfree(runtime->oss.buffer);
+       runtime->oss.buffer = NULL;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+       snd_pcm_oss_plugin_clear(substream);
+#endif
+       substream->oss.oss = 0;
 }
 
 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
@@ -1666,7 +1679,11 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime;
 
        substream->oss.oss = 1;
-       substream->oss.setup = setup;
+       substream->oss.setup = *setup;
+       if (setup->nonblock)
+               substream->ffile->f_flags |= O_NONBLOCK;
+       else if (setup->block)
+               substream->ffile->f_flags &= ~O_NONBLOCK;
        runtime = substream->runtime;
        runtime->oss.params = 1;
        runtime->oss.trigger = 1;
@@ -1685,16 +1702,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
        runtime->oss.fragshift = 0;
        runtime->oss.maxfrags = 0;
        runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime;
-       runtime = substream->runtime;
-       vfree(runtime->oss.buffer);
-       snd_pcm_oss_plugin_clear(substream);
-       substream->oss.file = NULL;
-       substream->oss.oss = 0;
+       substream->pcm_release = snd_pcm_oss_release_substream;
 }
 
 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1703,23 +1711,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
        snd_assert(pcm_oss_file != NULL, return -ENXIO);
        for (cidx = 0; cidx < 2; ++cidx) {
                struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
-               struct snd_pcm_runtime *runtime;
-               if (substream == NULL)
-                       continue;
-               runtime = substream->runtime;
-               
-               snd_pcm_stream_lock_irq(substream);
-               if (snd_pcm_running(substream))
-                       snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-               snd_pcm_stream_unlock_irq(substream);
-               if (substream->ffile != NULL) {
-                       if (substream->ops->hw_free != NULL)
-                               substream->ops->hw_free(substream);
-                       substream->ops->close(substream);
-                       substream->ffile = NULL;
-               }
-               snd_pcm_oss_release_substream(substream);
-               snd_pcm_release_substream(substream);
+               if (substream)
+                       snd_pcm_release_substream(substream);
        }
        kfree(pcm_oss_file);
        return 0;
@@ -1729,12 +1722,11 @@ static int snd_pcm_oss_open_file(struct file *file,
                                 struct snd_pcm *pcm,
                                 struct snd_pcm_oss_file **rpcm_oss_file,
                                 int minor,
-                                struct snd_pcm_oss_setup *psetup,
-                                struct snd_pcm_oss_setup *csetup)
+                                struct snd_pcm_oss_setup *setup)
 {
-       int err = 0;
+       int idx, err;
        struct snd_pcm_oss_file *pcm_oss_file;
-       struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
+       struct snd_pcm_substream *substream;
        unsigned int f_mode = file->f_mode;
 
        snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1747,73 +1739,32 @@ static int snd_pcm_oss_open_file(struct file *file,
        if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
            (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
                f_mode = FMODE_WRITE;
-       if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
-               if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                                              &psubstream)) < 0) {
+
+       for (idx = 0; idx < 2; idx++) {
+               if (setup[idx].disable)
+                       continue;
+               if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
+                       if (! (f_mode & FMODE_WRITE))
+                               continue;
+               } else {
+                       if (! (f_mode & FMODE_READ))
+                               continue;
+               }
+               err = snd_pcm_open_substream(pcm, idx, file, &substream);
+               if (err < 0) {
                        snd_pcm_oss_release_file(pcm_oss_file);
                        return err;
                }
-               pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
-       }
-       if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
-               if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 
-                                              &csubstream)) < 0) {
-                       if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
-                               snd_pcm_oss_release_file(pcm_oss_file);
-                               return err;
-                       } else {
-                               csubstream = NULL;
-                       }
-               }
-               pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
+
+               pcm_oss_file->streams[idx] = substream;
+               substream->file = pcm_oss_file;
+               snd_pcm_oss_init_substream(substream, &setup[idx], minor);
        }
        
-       if (psubstream == NULL && csubstream == NULL) {
+       if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
                snd_pcm_oss_release_file(pcm_oss_file);
                return -EINVAL;
        }
-       if (psubstream != NULL) {
-               psubstream->oss.file = pcm_oss_file;
-               err = snd_pcm_hw_constraints_init(psubstream);
-               if (err < 0) {
-                       snd_printd("snd_pcm_hw_constraint_init failed\n");
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               if ((err = psubstream->ops->open(psubstream)) < 0) {
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               psubstream->ffile = file;
-               err = snd_pcm_hw_constraints_complete(psubstream);
-               if (err < 0) {
-                       snd_printd("snd_pcm_hw_constraint_complete failed\n");
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               snd_pcm_oss_init_substream(psubstream, psetup, minor);
-       }
-       if (csubstream != NULL) {
-               csubstream->oss.file = pcm_oss_file;
-               err = snd_pcm_hw_constraints_init(csubstream);
-               if (err < 0) {
-                       snd_printd("snd_pcm_hw_constraint_init failed\n");
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               if ((err = csubstream->ops->open(csubstream)) < 0) {
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               csubstream->ffile = file;
-               err = snd_pcm_hw_constraints_complete(csubstream);
-               if (err < 0) {
-                       snd_printd("snd_pcm_hw_constraint_complete failed\n");
-                       snd_pcm_oss_release_file(pcm_oss_file);
-                       return err;
-               }
-               snd_pcm_oss_init_substream(csubstream, csetup, minor);
-       }
 
        file->private_data = pcm_oss_file;
        *rpcm_oss_file = pcm_oss_file;
@@ -1838,7 +1789,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        char task_name[32];
        struct snd_pcm *pcm;
        struct snd_pcm_oss_file *pcm_oss_file;
-       struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
+       struct snd_pcm_oss_setup setup[2];
        int nonblock;
        wait_queue_t wait;
 
@@ -1859,32 +1810,24 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                err = -EFAULT;
                goto __error;
        }
+       memset(setup, 0, sizeof(setup));
        if (file->f_mode & FMODE_WRITE)
-               psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+               snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                          task_name, &setup[0]);
        if (file->f_mode & FMODE_READ)
-               csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+               snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                          task_name, &setup[1]);
 
        nonblock = !!(file->f_flags & O_NONBLOCK);
-       if (psetup && !psetup->disable) {
-               if (psetup->nonblock)
-                       nonblock = 1;
-               else if (psetup->block)
-                       nonblock = 0;
-       } else if (csetup && !csetup->disable) {
-               if (csetup->nonblock)
-                       nonblock = 1;
-               else if (csetup->block)
-                       nonblock = 0;
-       }
        if (!nonblock)
                nonblock = nonblock_open;
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&pcm->open_wait, &wait);
-       down(&pcm->open_mutex);
+       mutex_lock(&pcm->open_mutex);
        while (1) {
                err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
-                                           iminor(inode), psetup, csetup);
+                                           iminor(inode), setup);
                if (err >= 0)
                        break;
                if (err == -EAGAIN) {
@@ -1895,16 +1838,16 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                } else
                        break;
                set_current_state(TASK_INTERRUPTIBLE);
-               up(&pcm->open_mutex);
+               mutex_unlock(&pcm->open_mutex);
                schedule();
-               down(&pcm->open_mutex);
+               mutex_lock(&pcm->open_mutex);
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
                }
        }
        remove_wait_queue(&pcm->open_wait, &wait);
-       up(&pcm->open_mutex);
+       mutex_unlock(&pcm->open_mutex);
        if (err < 0)
                goto __error;
        return err;
@@ -1930,9 +1873,9 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
        snd_assert(substream != NULL, return -ENXIO);
        pcm = substream->pcm;
        snd_pcm_oss_sync(pcm_oss_file);
-       down(&pcm->open_mutex);
+       mutex_lock(&pcm->open_mutex);
        snd_pcm_oss_release_file(pcm_oss_file);
-       up(&pcm->open_mutex);
+       mutex_unlock(&pcm->open_mutex);
        wake_up(&pcm->open_wait);
        module_put(pcm->card->module);
        snd_card_file_remove(pcm->card, file);
@@ -2135,9 +2078,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
        substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
        if (substream == NULL)
                return -ENXIO;
-       up(&file->f_dentry->d_inode->i_sem);
        result = snd_pcm_oss_write1(substream, buf, count);
-       down(&file->f_dentry->d_inode->i_sem);
 #ifdef OSS_DEBUG
        printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
 #endif
@@ -2248,8 +2189,10 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
                if ((err = snd_pcm_oss_change_params(substream)) < 0)
                        return err;
        }
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
        if (runtime->oss.plugin_first != NULL)
                return -EIO;
+#endif
 
        if (area->vm_pgoff != 0)
                return -EINVAL;
@@ -2269,6 +2212,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
        return 0;
 }
 
+#ifdef CONFIG_PROC_FS
 /*
  *  /proc interface
  */
@@ -2278,7 +2222,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
 {
        struct snd_pcm_str *pstr = entry->private_data;
        struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
-       down(&pstr->oss.setup_mutex);
+       mutex_lock(&pstr->oss.setup_mutex);
        while (setup) {
                snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
                            setup->task_name,
@@ -2292,18 +2236,13 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
                            setup->nosilence ? " no-silence" : "");
                setup = setup->next;
        }
-       up(&pstr->oss.setup_mutex);
+       mutex_unlock(&pstr->oss.setup_mutex);
 }
 
 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
 {
-       unsigned int idx;
-       struct snd_pcm_substream *substream;
        struct snd_pcm_oss_setup *setup, *setupn;
 
-       for (idx = 0, substream = pstr->substream;
-            idx < pstr->substream_count; idx++, substream = substream->next)
-               substream->oss.setup = NULL;
        for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
             setup; setup = setupn) {
                setupn = setup->next;
@@ -2322,12 +2261,12 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
        struct snd_pcm_oss_setup *setup, *setup1, template;
 
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
-               down(&pstr->oss.setup_mutex);
+               mutex_lock(&pstr->oss.setup_mutex);
                memset(&template, 0, sizeof(template));
                ptr = snd_info_get_str(task_name, line, sizeof(task_name));
                if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
                        snd_pcm_oss_proc_free_setup_list(pstr);
-                       up(&pstr->oss.setup_mutex);
+                       mutex_unlock(&pstr->oss.setup_mutex);
                        continue;
                }
                for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
@@ -2364,22 +2303,29 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
                        }
                } while (*str);
                if (setup == NULL) {
-                       setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
-                       if (setup) {
-                               if (pstr->oss.setup_list == NULL) {
-                                       pstr->oss.setup_list = setup;
-                               } else {
-                                       for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
-                                       setup1->next = setup;
-                               }
-                               template.task_name = kstrdup(task_name, GFP_KERNEL);
-                       } else {
+                       setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+                       if (! setup) {
+                               buffer->error = -ENOMEM;
+                               mutex_lock(&pstr->oss.setup_mutex);
+                               return;
+                       }
+                       if (pstr->oss.setup_list == NULL)
+                               pstr->oss.setup_list = setup;
+                       else {
+                               for (setup1 = pstr->oss.setup_list;
+                                    setup1->next; setup1 = setup1->next);
+                               setup1->next = setup;
+                       }
+                       template.task_name = kstrdup(task_name, GFP_KERNEL);
+                       if (! template.task_name) {
+                               kfree(setup);
                                buffer->error = -ENOMEM;
+                               mutex_lock(&pstr->oss.setup_mutex);
+                               return;
                        }
                }
-               if (setup)
-                       *setup = template;
-               up(&pstr->oss.setup_mutex);
+               *setup = template;
+               mutex_unlock(&pstr->oss.setup_mutex);
        }
 }
 
@@ -2420,6 +2366,10 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
                }
        }
 }
+#else /* !CONFIG_PROC_FS */
+#define snd_pcm_oss_proc_init(pcm)
+#define snd_pcm_oss_proc_done(pcm)
+#endif /* CONFIG_PROC_FS */
 
 /*
  *  ENTRY functions