]> Pileus Git - ~andy/linux/blobdiff - sound/core/pcm.c
[ALSA] Fix disconnection of proc interface
[~andy/linux] / sound / core / pcm.c
index 08223783cfa3317912dceb5515772e12acd5f1b7..b8602471f7e52d326e5a919eb900ef2d03303ea7 100644 (file)
@@ -351,10 +351,8 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "closed\n");
                return;
        }
-       snd_pcm_stream_lock_irq(substream);
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                snd_iprintf(buffer, "no setup\n");
-               snd_pcm_stream_unlock_irq(substream);
                return;
        }
        snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
@@ -375,7 +373,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
        }
 #endif
-       snd_pcm_stream_unlock_irq(substream);
 }
 
 static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
@@ -387,10 +384,8 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "closed\n");
                return;
        }
-       snd_pcm_stream_lock_irq(substream);
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                snd_iprintf(buffer, "no setup\n");
-               snd_pcm_stream_unlock_irq(substream);
                return;
        }
        snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
@@ -403,7 +398,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
        snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
        snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
-       snd_pcm_stream_unlock_irq(substream);
 }
 
 static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
@@ -500,19 +494,13 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
 static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
 {
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
-       if (pstr->proc_xrun_debug_entry) {
-               snd_info_unregister(pstr->proc_xrun_debug_entry);
-               pstr->proc_xrun_debug_entry = NULL;
-       }
+       snd_info_free_entry(pstr->proc_xrun_debug_entry);
+       pstr->proc_xrun_debug_entry = NULL;
 #endif
-       if (pstr->proc_info_entry) {
-               snd_info_unregister(pstr->proc_info_entry);
-               pstr->proc_info_entry = NULL;
-       }
-       if (pstr->proc_root) {
-               snd_info_unregister(pstr->proc_root);
-               pstr->proc_root = NULL;
-       }
+       snd_info_free_entry(pstr->proc_info_entry);
+       pstr->proc_info_entry = NULL;
+       snd_info_free_entry(pstr->proc_root);
+       pstr->proc_root = NULL;
        return 0;
 }
 
@@ -576,29 +564,19 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
 
        return 0;
 }
-               
+
 static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
 {
-       if (substream->proc_info_entry) {
-               snd_info_unregister(substream->proc_info_entry);
-               substream->proc_info_entry = NULL;
-       }
-       if (substream->proc_hw_params_entry) {
-               snd_info_unregister(substream->proc_hw_params_entry);
-               substream->proc_hw_params_entry = NULL;
-       }
-       if (substream->proc_sw_params_entry) {
-               snd_info_unregister(substream->proc_sw_params_entry);
-               substream->proc_sw_params_entry = NULL;
-       }
-       if (substream->proc_status_entry) {
-               snd_info_unregister(substream->proc_status_entry);
-               substream->proc_status_entry = NULL;
-       }
-       if (substream->proc_root) {
-               snd_info_unregister(substream->proc_root);
-               substream->proc_root = NULL;
-       }
+       snd_info_free_entry(substream->proc_info_entry);
+       substream->proc_info_entry = NULL;
+       snd_info_free_entry(substream->proc_hw_params_entry);
+       substream->proc_hw_params_entry = NULL;
+       snd_info_free_entry(substream->proc_sw_params_entry);
+       substream->proc_sw_params_entry = NULL;
+       snd_info_free_entry(substream->proc_status_entry);
+       substream->proc_status_entry = NULL;
+       snd_info_free_entry(substream->proc_root);
+       substream->proc_root = NULL;
        return 0;
 }
 #else /* !CONFIG_SND_VERBOSE_PROCFS */
@@ -668,6 +646,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
                INIT_LIST_HEAD(&substream->self_group.substreams);
                list_add_tail(&substream->link_list, &substream->self_group.substreams);
                spin_lock_init(&substream->timer_lock);
+               atomic_set(&substream->mmap_count, 0);
                prev = substream;
        }
        return 0;
@@ -835,6 +814,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
                return -EINVAL;
        }
 
+       if (file->f_flags & O_APPEND) {
+               if (prefer_subdevice < 0) {
+                       if (pstr->substream_count > 1)
+                               return -EINVAL; /* must be unique */
+                       substream = pstr->substream;
+               } else {
+                       for (substream = pstr->substream; substream;
+                            substream = substream->next)
+                               if (substream->number == prefer_subdevice)
+                                       break;
+               }
+               if (! substream)
+                       return -ENODEV;
+               if (! SUBSTREAM_BUSY(substream))
+                       return -EBADFD;
+               substream->ref_count++;
+               *rsubstream = substream;
+               return 0;
+       }
+
        if (prefer_subdevice >= 0) {
                for (substream = pstr->substream; substream; substream = substream->next)
                        if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
@@ -870,7 +869,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
        memset((void*)runtime->control, 0, size);
 
        init_waitqueue_head(&runtime->sleep);
-       atomic_set(&runtime->mmap_count, 0);
        init_timer(&runtime->tick_timer);
        runtime->tick_timer.function = snd_pcm_tick_timer_func;
        runtime->tick_timer.data = (unsigned long) substream;
@@ -879,7 +877,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
 
        substream->runtime = runtime;
        substream->private_data = pcm->private_data;
-       substream->ffile = file;
+       substream->ref_count = 1;
+       substream->f_flags = file->f_flags;
        pstr->substream_opened++;
        *rsubstream = substream;
        return 0;
@@ -888,7 +887,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
 void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
-       substream->file = NULL;
+
        runtime = substream->runtime;
        snd_assert(runtime != NULL, return);
        if (runtime->private_free != NULL)
@@ -1057,7 +1056,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
        mutex_unlock(&register_mutex);
 }
 
-static struct snd_info_entry *snd_pcm_proc_entry = NULL;
+static struct snd_info_entry *snd_pcm_proc_entry;
 
 static void snd_pcm_proc_init(void)
 {
@@ -1075,8 +1074,7 @@ static void snd_pcm_proc_init(void)
 
 static void snd_pcm_proc_done(void)
 {
-       if (snd_pcm_proc_entry)
-               snd_info_unregister(snd_pcm_proc_entry);
+       snd_info_free_entry(snd_pcm_proc_entry);
 }
 
 #else /* !CONFIG_PROC_FS */