ALSA: pcm: Add xrun_injection proc entry
authorTakashi Iwai <tiwai@suse.de>
Tue, 4 Nov 2014 13:02:40 +0000 (14:02 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 4 Nov 2014 13:09:16 +0000 (14:09 +0100)
This patch adds a new proc entry for PCM substreams to inject an
XRUN.  When a PCM substream is running and any value is written to its
xrun_injection proc file, the driver triggers XRUN.  This is a useful
feature for debugging XRUN and error handling code paths.

Note that this entry is enabled only when CONFIG_SND_PCM_XRUN_DEBUG is
set.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Documentation/sound/alsa/Procfile.txt
include/sound/pcm.h
sound/core/pcm.c

index cfc4956..7f8a0d3 100644 (file)
@@ -133,6 +133,10 @@ card*/pcm*/sub*/sw_params
 card*/pcm*/sub*/prealloc
        The buffer pre-allocation information.
 
+card*/pcm*/sub*/xrun_injection
+       Triggers an XRUN to the running stream when any value is
+       written to this proc file.  Used for fault injection.
+       This entry is write-only.
 
 AC97 Codec Information
 ----------------------
index 29eb09e..0b8daee 100644 (file)
@@ -416,7 +416,10 @@ struct snd_pcm_substream {
        struct snd_info_entry *proc_status_entry;
        struct snd_info_entry *proc_prealloc_entry;
        struct snd_info_entry *proc_prealloc_max_entry;
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+       struct snd_info_entry *proc_xrun_injection_entry;
 #endif
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
        /* misc flags */
        unsigned int hw_opened: 1;
 };
index 31acc3d..8f624b7 100644 (file)
@@ -483,6 +483,19 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 }
 
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
+static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry,
+                                        struct snd_info_buffer *buffer)
+{
+       struct snd_pcm_substream *substream = entry->private_data;
+       struct snd_pcm_runtime *runtime;
+
+       snd_pcm_stream_lock_irq(substream);
+       runtime = substream->runtime;
+       if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+               snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
                                    struct snd_info_buffer *buffer)
 {
@@ -614,6 +627,22 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
        }
        substream->proc_status_entry = entry;
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+       entry = snd_info_create_card_entry(card, "xrun_injection",
+                                          substream->proc_root);
+       if (entry) {
+               entry->private_data = substream;
+               entry->c.text.read = NULL;
+               entry->c.text.write = snd_pcm_xrun_injection_write;
+               entry->mode = S_IFREG | S_IWUSR;
+               if (snd_info_register(entry) < 0) {
+                       snd_info_free_entry(entry);
+                       entry = NULL;
+               }
+       }
+       substream->proc_xrun_injection_entry = entry;
+#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
+
        return 0;
 }
 
@@ -627,6 +656,10 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
        substream->proc_sw_params_entry = NULL;
        snd_info_free_entry(substream->proc_status_entry);
        substream->proc_status_entry = NULL;
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+       snd_info_free_entry(substream->proc_xrun_injection_entry);
+       substream->proc_xrun_injection_entry = NULL;
+#endif
        snd_info_free_entry(substream->proc_root);
        substream->proc_root = NULL;
        return 0;