Loading include/sound/pcm.h +0 −1 Original line number Diff line number Diff line Loading @@ -364,7 +364,6 @@ struct snd_pcm_substream { /* -- timer section -- */ struct snd_timer *timer; /* timer */ unsigned timer_running: 1; /* time is running */ spinlock_t timer_lock; /* -- next substream -- */ struct snd_pcm_substream *next; /* -- linked substreams -- */ Loading sound/core/pcm.c +0 −1 Original line number Diff line number Diff line Loading @@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) spin_lock_init(&substream->self_group.lock); 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; } Loading sound/core/pcm_lib.c +102 −53 Original line number Diff line number Diff line Loading @@ -125,22 +125,31 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } } #ifdef CONFIG_SND_PCM_XRUN_DEBUG #define xrun_debug(substream) ((substream)->pstr->xrun_debug) #else #define xrun_debug(substream) 0 #endif #define dump_stack_on_xrun(substream) do { \ if (xrun_debug(substream) > 1) \ dump_stack(); \ } while (0) static void xrun(struct snd_pcm_substream *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (substream->pstr->xrun_debug) { if (xrun_debug(substream)) { snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", substream->pcm->card->number, substream->pcm->device, substream->stream ? 'c' : 'p'); if (substream->pstr->xrun_debug > 1) dump_stack(); dump_stack_on_xrun(substream); } #endif } static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, static snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t pos; Loading @@ -150,16 +159,20 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre pos = substream->ops->pointer(substream); if (pos == SNDRV_PCM_POS_XRUN) return pos; /* XRUN */ #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); if (printk_ratelimit()) { snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, " "buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); } pos = 0; } #endif pos -= pos % runtime->min_align; return pos; } static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t avail; Loading @@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream return 0; } static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) #define hw_ptr_error(substream, fmt, args...) \ do { \ if (xrun_debug(substream)) { \ if (printk_ratelimit()) { \ snd_printd("PCM: " fmt, ##args); \ } \ dump_stack_on_xrun(substream); \ } \ } while (0) static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt; snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base; snd_pcm_sframes_t delta; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); Loading @@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs xrun(substream); return -EPIPE; } if (runtime->period_size == runtime->buffer_size) goto __next_buf; new_hw_ptr = runtime->hw_ptr_base + pos; hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; delta = hw_ptr_interrupt - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 1 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) dump_stack(); } #endif return 0; } __next_buf: runtime->hw_ptr_base += runtime->buffer_size; if (runtime->hw_ptr_base == runtime->boundary) runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; delta = new_hw_ptr - hw_ptr_interrupt; if (hw_ptr_interrupt >= runtime->boundary) { hw_ptr_interrupt -= runtime->boundary; if (hw_base < runtime->boundary / 2) /* hw_base was already lapped; recalc delta */ delta = new_hw_ptr - hw_ptr_interrupt; } if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value " "(stream=%i, pos=%ld, intr_ptr=%ld)\n", substream->stream, (long)pos, (long)hw_ptr_interrupt); /* rebase to interrupt position */ hw_base = new_hw_ptr = hw_ptr_interrupt; /* align hw_base to buffer_size */ hw_base -= hw_base % runtime->buffer_size; delta = 0; } else { hw_base += runtime->buffer_size; if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } } if (delta > runtime->period_size) { hw_ptr_error(substream, "Lost interrupts? " "(stream=%i, delta=%ld, intr_ptr=%ld)\n", substream->stream, (long)delta, (long)hw_ptr_interrupt); /* rebase hw_ptr_interrupt */ hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, new_hw_ptr); runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; runtime->hw_ptr_interrupt = hw_ptr_interrupt; return snd_pcm_update_hw_ptr_post(substream, runtime); } Loading @@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; snd_pcm_sframes_t delta; old_hw_ptr = runtime->status->hw_ptr; Loading @@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) xrun(substream); return -EPIPE; } new_hw_ptr = runtime->hw_ptr_base + pos; delta = old_hw_ptr - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 2 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) dump_stack(); } #endif hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; delta = new_hw_ptr - old_hw_ptr; if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value [2] " "(stream=%i, pos=%ld, old_ptr=%ld)\n", substream->stream, (long)pos, (long)old_hw_ptr); return 0; } runtime->hw_ptr_base += runtime->buffer_size; if (runtime->hw_ptr_base == runtime->boundary) runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; hw_base += runtime->buffer_size; if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } if (delta > runtime->period_size && runtime->periods > 1) { hw_ptr_error(substream, "hw_ptr skipping! " "(pos=%ld, delta=%ld, period=%ld)\n", (long)pos, (long)delta, (long)runtime->period_size); return 0; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, new_hw_ptr); runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; return snd_pcm_update_hw_ptr_post(substream, runtime); Loading sound/core/pcm_timer.c +0 −6 Original line number Diff line number Diff line Loading @@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) static int snd_pcm_timer_start(struct snd_timer * timer) { unsigned long flags; struct snd_pcm_substream *substream; substream = snd_timer_chip(timer); spin_lock_irqsave(&substream->timer_lock, flags); substream->timer_running = 1; spin_unlock_irqrestore(&substream->timer_lock, flags); return 0; } static int snd_pcm_timer_stop(struct snd_timer * timer) { unsigned long flags; struct snd_pcm_substream *substream; substream = snd_timer_chip(timer); spin_lock_irqsave(&substream->timer_lock, flags); substream->timer_running = 0; spin_unlock_irqrestore(&substream->timer_lock, flags); return 0; } Loading Loading
include/sound/pcm.h +0 −1 Original line number Diff line number Diff line Loading @@ -364,7 +364,6 @@ struct snd_pcm_substream { /* -- timer section -- */ struct snd_timer *timer; /* timer */ unsigned timer_running: 1; /* time is running */ spinlock_t timer_lock; /* -- next substream -- */ struct snd_pcm_substream *next; /* -- linked substreams -- */ Loading
sound/core/pcm.c +0 −1 Original line number Diff line number Diff line Loading @@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) spin_lock_init(&substream->self_group.lock); 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; } Loading
sound/core/pcm_lib.c +102 −53 Original line number Diff line number Diff line Loading @@ -125,22 +125,31 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } } #ifdef CONFIG_SND_PCM_XRUN_DEBUG #define xrun_debug(substream) ((substream)->pstr->xrun_debug) #else #define xrun_debug(substream) 0 #endif #define dump_stack_on_xrun(substream) do { \ if (xrun_debug(substream) > 1) \ dump_stack(); \ } while (0) static void xrun(struct snd_pcm_substream *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (substream->pstr->xrun_debug) { if (xrun_debug(substream)) { snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", substream->pcm->card->number, substream->pcm->device, substream->stream ? 'c' : 'p'); if (substream->pstr->xrun_debug > 1) dump_stack(); dump_stack_on_xrun(substream); } #endif } static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, static snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t pos; Loading @@ -150,16 +159,20 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre pos = substream->ops->pointer(substream); if (pos == SNDRV_PCM_POS_XRUN) return pos; /* XRUN */ #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); if (printk_ratelimit()) { snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, " "buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); } pos = 0; } #endif pos -= pos % runtime->min_align; return pos; } static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t avail; Loading @@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream return 0; } static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) #define hw_ptr_error(substream, fmt, args...) \ do { \ if (xrun_debug(substream)) { \ if (printk_ratelimit()) { \ snd_printd("PCM: " fmt, ##args); \ } \ dump_stack_on_xrun(substream); \ } \ } while (0) static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt; snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base; snd_pcm_sframes_t delta; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); Loading @@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs xrun(substream); return -EPIPE; } if (runtime->period_size == runtime->buffer_size) goto __next_buf; new_hw_ptr = runtime->hw_ptr_base + pos; hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; delta = hw_ptr_interrupt - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 1 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) dump_stack(); } #endif return 0; } __next_buf: runtime->hw_ptr_base += runtime->buffer_size; if (runtime->hw_ptr_base == runtime->boundary) runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; delta = new_hw_ptr - hw_ptr_interrupt; if (hw_ptr_interrupt >= runtime->boundary) { hw_ptr_interrupt -= runtime->boundary; if (hw_base < runtime->boundary / 2) /* hw_base was already lapped; recalc delta */ delta = new_hw_ptr - hw_ptr_interrupt; } if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value " "(stream=%i, pos=%ld, intr_ptr=%ld)\n", substream->stream, (long)pos, (long)hw_ptr_interrupt); /* rebase to interrupt position */ hw_base = new_hw_ptr = hw_ptr_interrupt; /* align hw_base to buffer_size */ hw_base -= hw_base % runtime->buffer_size; delta = 0; } else { hw_base += runtime->buffer_size; if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } } if (delta > runtime->period_size) { hw_ptr_error(substream, "Lost interrupts? " "(stream=%i, delta=%ld, intr_ptr=%ld)\n", substream->stream, (long)delta, (long)hw_ptr_interrupt); /* rebase hw_ptr_interrupt */ hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, new_hw_ptr); runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; runtime->hw_ptr_interrupt = hw_ptr_interrupt; return snd_pcm_update_hw_ptr_post(substream, runtime); } Loading @@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; snd_pcm_sframes_t delta; old_hw_ptr = runtime->status->hw_ptr; Loading @@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) xrun(substream); return -EPIPE; } new_hw_ptr = runtime->hw_ptr_base + pos; delta = old_hw_ptr - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { #ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 2 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) dump_stack(); } #endif hw_base = runtime->hw_ptr_base; new_hw_ptr = hw_base + pos; delta = new_hw_ptr - old_hw_ptr; if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value [2] " "(stream=%i, pos=%ld, old_ptr=%ld)\n", substream->stream, (long)pos, (long)old_hw_ptr); return 0; } runtime->hw_ptr_base += runtime->buffer_size; if (runtime->hw_ptr_base == runtime->boundary) runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; hw_base += runtime->buffer_size; if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } if (delta > runtime->period_size && runtime->periods > 1) { hw_ptr_error(substream, "hw_ptr skipping! " "(pos=%ld, delta=%ld, period=%ld)\n", (long)pos, (long)delta, (long)runtime->period_size); return 0; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, new_hw_ptr); runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; return snd_pcm_update_hw_ptr_post(substream, runtime); Loading
sound/core/pcm_timer.c +0 −6 Original line number Diff line number Diff line Loading @@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) static int snd_pcm_timer_start(struct snd_timer * timer) { unsigned long flags; struct snd_pcm_substream *substream; substream = snd_timer_chip(timer); spin_lock_irqsave(&substream->timer_lock, flags); substream->timer_running = 1; spin_unlock_irqrestore(&substream->timer_lock, flags); return 0; } static int snd_pcm_timer_stop(struct snd_timer * timer) { unsigned long flags; struct snd_pcm_substream *substream; substream = snd_timer_chip(timer); spin_lock_irqsave(&substream->timer_lock, flags); substream->timer_running = 0; spin_unlock_irqrestore(&substream->timer_lock, flags); return 0; } Loading