diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c index 667dda3f043978..deea9e3d882439 100644 --- a/sound/soc/sof/ipc4-mtrace.c +++ b/sound/soc/sof/ipc4-mtrace.c @@ -109,6 +109,26 @@ static int sof_ipc4_mtrace_dfs_open(struct inode *inode, struct file *file) return -ENOMEM; } + /* + * Re-sync dsp_write_ptr from SRAM and align host_read_ptr to it so + * this reader starts from current write position and only sees + * data written after this open(). Without this prior reader (e.g. + * one-shot dd) may have advanced host_read_ptr to equal + * dsp_write_ptr, causing next reader to block indefinitely on + * platforms with low DSP activity.Resetting to current dsp_write_ptr + * (not to 0) avoids re-reading stale data from wrapped circular buffer. + */ + if (core_data->slot_offset != SOF_IPC4_INVALID_SLOT_OFFSET) { + struct snd_sof_dev *sdev = core_data->sdev; + u32 write_ptr; + + sof_mailbox_read(sdev, core_data->slot_offset + sizeof(u32), + &write_ptr, sizeof(write_ptr)); + write_ptr -= write_ptr % 4; + core_data->dsp_write_ptr = write_ptr; + core_data->host_read_ptr = write_ptr; + } + ret = simple_open(inode, file); if (ret) { kfree(core_data->log_buffer); @@ -254,6 +274,14 @@ static int sof_ipc4_mtrace_dfs_release(struct inode *inode, struct file *file) scoped_guard(mutex, &core_data->buffer_lock) { kfree(core_data->log_buffer); core_data->log_buffer = NULL; + /* + * Align host_read_ptr to current dsp_write_ptr so that + * subsequent open() starts from fresh data and isnt + * blocked by stale pointer left by this reader. Using + * dsp_write_ptr (not 0) avoids re-reading stale data from + * wrapped circular buffer. + */ + core_data->host_read_ptr = core_data->dsp_write_ptr; } return 0;