diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-25 15:55:03 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-25 15:55:03 -0700 |
| commit | 75467f60a3d14f08f86f2b353298d2826382ff23 (patch) | |
| tree | acd8a7d5b5a675042449386efa5b42ec44d8bf81 /sound/soc/sof/stream-ipc.c | |
| download | linux-stable-75467f60a3d14f08f86f2b353298d2826382ff23.tar.gz linux-stable-75467f60a3d14f08f86f2b353298d2826382ff23.zip | |
Merge tag 'ipe-pr-20260925' of git://git.kernel.org/pub/scm/linux/kernel/git/wufan/ipegrafted
Pull IPE fixes from Fan Wu:
"Two fixes for use-after-free issues found by recent LLM-assisted code
analysis.
- move successful policy load auditing under the new policy
directory's inode lock, preventing a concurrent policy deletion
from freeing the policy while it is still being audited
- protect the dm-verity root hash with RCU, preventing policy
evaluation from racing with root hash replacement during preresume"
* tag 'ipe-pr-20260925' of git://git.kernel.org/pub/scm/linux/kernel/git/wufan/ipe:
ipe: protect the dm-verity root hash with RCU
ipe: fix use-after-free when auditing a newly loaded policy
Diffstat (limited to 'sound/soc/sof/stream-ipc.c')
| -rw-r--r-- | sound/soc/sof/stream-ipc.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/sound/soc/sof/stream-ipc.c b/sound/soc/sof/stream-ipc.c new file mode 100644 index 000000000..78758cf58 --- /dev/null +++ b/sound/soc/sof/stream-ipc.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019 Intel Corporation +// +// Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> + +/* Generic SOF IPC code */ + +#include <linux/device.h> +#include <linux/export.h> +#include <linux/module.h> +#include <linux/types.h> + +#include <sound/pcm.h> +#include <sound/sof/stream.h> + +#include "ops.h" +#include "sof-priv.h" +#include "sof-audio.h" + +struct sof_stream { + size_t posn_offset; +}; + +/* Mailbox-based Generic IPC implementation */ +int sof_ipc_msg_data(struct snd_sof_dev *sdev, + struct snd_sof_pcm_stream *sps, + void *p, size_t sz) +{ + if (!sps || !sdev->stream_box.size) { + snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); + } else { + size_t posn_offset; + + if (sps->substream) { + struct sof_stream *stream = sps->substream->runtime->private_data; + + /* The stream might already be closed */ + if (!stream) + return -ESTRPIPE; + + posn_offset = stream->posn_offset; + } else if (sps->cstream) { + + struct sof_compr_stream *sstream = sps->cstream->runtime->private_data; + + if (!sstream) + return -ESTRPIPE; + + posn_offset = sstream->posn_offset; + + } else { + dev_err(sdev->dev, "%s: No stream opened\n", __func__); + return -EINVAL; + } + + snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz); + } + + return 0; +} +EXPORT_SYMBOL(sof_ipc_msg_data); + +int sof_set_stream_data_offset(struct snd_sof_dev *sdev, + struct snd_sof_pcm_stream *sps, + size_t posn_offset) +{ + /* check if offset is overflow or it is not aligned */ + if (posn_offset > sdev->stream_box.size || + posn_offset % sizeof(struct sof_ipc_stream_posn) != 0) + return -EINVAL; + + posn_offset += sdev->stream_box.offset; + + if (sps->substream) { + struct sof_stream *stream = sps->substream->runtime->private_data; + + stream->posn_offset = posn_offset; + dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu", + sps->substream->stream, posn_offset); + } else if (sps->cstream) { + struct sof_compr_stream *sstream = sps->cstream->runtime->private_data; + + sstream->posn_offset = posn_offset; + dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu", + sps->cstream->direction, posn_offset); + } else { + dev_err(sdev->dev, "No stream opened"); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(sof_set_stream_data_offset); + +int sof_stream_pcm_open(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct sof_stream *stream = kmalloc_obj(*stream); + + if (!stream) + return -ENOMEM; + + /* binding pcm substream to hda stream */ + substream->runtime->private_data = stream; + + /* align to DMA minimum transfer size */ + snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); + + /* avoid circular buffer wrap in middle of period */ + snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + + return 0; +} +EXPORT_SYMBOL(sof_stream_pcm_open); + +int sof_stream_pcm_close(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct sof_stream *stream = substream->runtime->private_data; + + substream->runtime->private_data = NULL; + kfree(stream); + + return 0; +} +EXPORT_SYMBOL(sof_stream_pcm_close); |
