Skip to content

Commit 5bce200

Browse files
committed
ASoC: SOF: trace: Add helper function to update the sdev->host_offset
We are using the READ_ONCE() on the debugfs read path for accessing sdev->host_offset, but the set is not atomic or protected in any way. Add a small helper to do the host_offset update and be really paranoid about the a possible race in update Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent 4394639 commit 5bce200

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

sound/soc/sof/trace.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,21 @@ static int trace_debugfs_filter_create(struct snd_sof_dev *sdev)
233233
return 0;
234234
}
235235

236+
static bool sof_trace_set_host_offset(struct snd_sof_dev *sdev, u32 new_offset)
237+
{
238+
u32 host_offset = READ_ONCE(sdev->host_offset);
239+
240+
if (host_offset != new_offset) {
241+
/* This is a bit paranoid and unlikely that it is needed */
242+
u32 ret = cmpxchg(&sdev->host_offset, host_offset, new_offset);
243+
244+
if (ret == host_offset)
245+
return true;
246+
}
247+
248+
return false;
249+
}
250+
236251
static size_t sof_trace_avail(struct snd_sof_dev *sdev,
237252
loff_t pos, size_t buffer_size)
238253
{
@@ -345,7 +360,7 @@ static int sof_dfsentry_trace_release(struct inode *inode, struct file *file)
345360

346361
/* avoid duplicate traces at next open */
347362
if (sdev->dtrace_state != SOF_DTRACE_ENABLED)
348-
sdev->host_offset = 0;
363+
sof_trace_set_host_offset(sdev, 0);
349364

350365
return 0;
351366
}
@@ -417,7 +432,7 @@ static int snd_sof_enable_trace(struct snd_sof_dev *sdev)
417432
params.buffer.pages = sdev->dma_trace_pages;
418433
params.stream_tag = 0;
419434

420-
sdev->host_offset = 0;
435+
sof_trace_set_host_offset(sdev, 0);
421436
sdev->dtrace_draining = false;
422437

423438
ret = snd_sof_dma_trace_init(sdev, &params);
@@ -524,10 +539,9 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev,
524539
if (!sdev->dtrace_is_supported)
525540
return 0;
526541

527-
if (sdev->dtrace_state == SOF_DTRACE_ENABLED &&
528-
sdev->host_offset != posn->host_offset) {
529-
sdev->host_offset = posn->host_offset;
530-
wake_up(&sdev->trace_sleep);
542+
if (sdev->dtrace_state == SOF_DTRACE_ENABLED) {
543+
if (sof_trace_set_host_offset(sdev, posn->host_offset))
544+
wake_up(&sdev->trace_sleep);
531545
}
532546

533547
if (posn->overflow != 0)

0 commit comments

Comments
 (0)