#define XRUN_LOG_CNT 10
struct hwptr_log_entry {
+ unsigned int in_interrupt;
unsigned long jiffies;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t period_size;
};
static void xrun_log(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t pos)
+ snd_pcm_uframes_t pos, int in_interrupt)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hwptr_log *log = runtime->hwptr_log;
return;
}
entry = &log->entries[log->idx];
+ entry->in_interrupt = in_interrupt;
entry->jiffies = jiffies;
entry->pos = pos;
entry->period_size = runtime->period_size;
entry = &log->entries[idx];
if (entry->period_size == 0)
break;
- snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
+ snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, "
"hwptr=%ld/%ld\n",
- name, entry->jiffies, (unsigned long)entry->pos,
+ name, entry->in_interrupt ? "[Q] " : "",
+ entry->jiffies,
+ (unsigned long)entry->pos,
(unsigned long)entry->period_size,
(unsigned long)entry->buffer_size,
(unsigned long)entry->old_hw_ptr,
#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
#define hw_ptr_error(substream, fmt, args...) do { } while (0)
-#define xrun_log(substream, pos) do { } while (0)
+#define xrun_log(substream, pos, in_interrupt) do { } while (0)
#define xrun_log_show(substream) do { } while (0)
#endif
}
pos -= pos % runtime->min_align;
if (xrun_debug(substream, XRUN_DEBUG_LOG))
- xrun_log(substream, pos);
+ xrun_log(substream, pos, in_interrupt);
hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos;
if (in_interrupt) {
wait_queue_t wait;
int err = 0;
snd_pcm_uframes_t avail = 0;
- long tout;
-
+ long wait_time, tout;
+
+ if (runtime->no_period_wakeup)
+ wait_time = MAX_SCHEDULE_TIMEOUT;
+ else {
+ wait_time = 10;
+ if (runtime->rate) {
+ long t = runtime->period_size * 2 / runtime->rate;
+ wait_time = max(t, wait_time);
+ }
+ wait_time = msecs_to_jiffies(wait_time * 1000);
+ }
init_waitqueue_entry(&wait, current);
add_wait_queue(&runtime->tsleep, &wait);
for (;;) {
err = -ERESTARTSYS;
break;
}
- set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
- tout = schedule_timeout(msecs_to_jiffies(10000));
+ tout = schedule_timeout_interruptible(wait_time);
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED: