Skip to content

Commit

Permalink
ALSA: firewire-lib: permit to flush queued packets only in process co…
Browse files Browse the repository at this point in the history
…ntext for better PCM period granularity

These three commits were merged to improve PCM pointer granularity.
commit 76fb878 ("ALSA: firewire-lib: taskletize the snd_pcm_period_elapsed() call")
commit e9148dd ("ALSA: firewire-lib: flush completed packets when reading PCM position")
commit 92b862c ("ALSA: firewire-lib: optimize packet flushing")

The point of them is to handle queued packets not only in software IRQ
context of IR/IT contexts, but also in process context. As a result of
handling packets, period tasklet is scheduled when acrossing PCM period
boundary. This is to prevent recursive call of
'struct snd_pcm_ops.pointer()' in the same context.

When the pointer callback is executed in the process context, it's
better to avoid the second callback in the software IRQ context. The
software IRQ context runs immediately after scheduled in the process
context because few packets are queued yet.

For the aim, 'pointer_flush' is used, however it causes a race condition
between the process context and software IRQ context of IR/IT contexts.

Practically, this race is not so critical because it influences process
context to skip flushing queued packet and to get worse granularity of
PCM pointer. The race condition is quite rare but it should be improved
for stable service.

The similar effect can be achieved by using 'in_interrupt()' macro. This
commit obsoletes 'pointer_flush' with it.

Acked-by: Clemens Ladisch <[email protected]>
Signed-off-by: Takashi Sakamoto <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
takaswie authored and tiwai committed May 11, 2016
1 parent 8d879be commit 1dba9db
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
23 changes: 17 additions & 6 deletions sound/firewire/amdtp-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ void amdtp_stream_pcm_prepare(struct amdtp_stream *s)
tasklet_kill(&s->period_tasklet);
s->pcm_buffer_pointer = 0;
s->pcm_period_pointer = 0;
s->pointer_flush = true;
}
EXPORT_SYMBOL(amdtp_stream_pcm_prepare);

Expand Down Expand Up @@ -356,7 +355,6 @@ static void update_pcm_pointers(struct amdtp_stream *s,
s->pcm_period_pointer += frames;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
s->pointer_flush = false;
tasklet_hi_schedule(&s->period_tasklet);
}
}
Expand Down Expand Up @@ -803,11 +801,24 @@ EXPORT_SYMBOL(amdtp_stream_start);
*/
unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s)
{
/* this optimization is allowed to be racy */
if (s->pointer_flush && amdtp_stream_running(s))
/*
* This function is called in software IRQ context of period_tasklet or
* process context.
*
* When the software IRQ context was scheduled by software IRQ context
* of IR/IT contexts, queued packets were already handled. Therefore,
* no need to flush the queue in buffer anymore.
*
* When the process context reach here, some packets will be already
* queued in the buffer. These packets should be handled immediately
* to keep better granularity of PCM pointer.
*
* Later, the process context will sometimes schedules software IRQ
* context of the period_tasklet. Then, no need to flush the queue by
* the same reason as described for IR/IT contexts.
*/
if (!in_interrupt() && amdtp_stream_running(s))
fw_iso_context_flush_completions(s->context);
else
s->pointer_flush = true;

return ACCESS_ONCE(s->pcm_buffer_pointer);
}
Expand Down
1 change: 0 additions & 1 deletion sound/firewire/amdtp-stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ struct amdtp_stream {
struct tasklet_struct period_tasklet;
unsigned int pcm_buffer_pointer;
unsigned int pcm_period_pointer;
bool pointer_flush;

/* To wait for first packet. */
bool callbacked;
Expand Down

0 comments on commit 1dba9db

Please sign in to comment.