mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
ASoC: Intel: catpt: Synchronize stream access
Streams may have individual controls assigned to them e.g.: volume control in case of offload streams. If such a stream is running and simultaneously its controls are being manipulated, both processes are touching the exact same descriptors - access to these must be synchronized. Replace spinlock with mutex as IPCs are non-atomic operations and add proper locking for all ->stream_list users. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/20260309091605.896307-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
1f318b96cc
commit
b0b49c77bd
|
|
@ -96,7 +96,7 @@ struct catpt_dev {
|
|||
struct catpt_module_type modules[CATPT_MODULE_COUNT];
|
||||
struct catpt_ssp_device_format devfmt[CATPT_SSP_COUNT];
|
||||
struct list_head stream_list;
|
||||
spinlock_t list_lock;
|
||||
struct mutex stream_mutex;
|
||||
struct mutex clk_mutex;
|
||||
|
||||
struct catpt_dx_context dx_ctx;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ static void catpt_dev_init(struct catpt_dev *cdev, struct device *dev,
|
|||
cdev->spec = spec;
|
||||
init_completion(&cdev->fw_ready);
|
||||
INIT_LIST_HEAD(&cdev->stream_list);
|
||||
spin_lock_init(&cdev->list_lock);
|
||||
mutex_init(&cdev->stream_mutex);
|
||||
mutex_init(&cdev->clk_mutex);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
|
||||
//
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include "core.h"
|
||||
#include "messages.h"
|
||||
|
|
@ -151,6 +152,8 @@ catpt_dsp_notify_stream(struct catpt_dev *cdev, union catpt_notify_msg msg)
|
|||
struct catpt_notify_position pos;
|
||||
struct catpt_notify_glitch glitch;
|
||||
|
||||
guard(mutex)(&cdev->stream_mutex);
|
||||
|
||||
stream = catpt_stream_find(cdev, msg.stream_hw_id);
|
||||
if (!stream) {
|
||||
dev_warn(cdev->dev, "notify %d for non-existent stream %d\n",
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ int catpt_store_streams_context(struct catpt_dev *cdev, struct dma_chan *chan)
|
|||
{
|
||||
struct catpt_stream_runtime *stream;
|
||||
|
||||
/* Lockless as no streams can be added or removed during D3 -> D0 transition. */
|
||||
list_for_each_entry(stream, &cdev->stream_list, node) {
|
||||
u32 off, size;
|
||||
int ret;
|
||||
|
|
@ -180,6 +181,7 @@ catpt_restore_streams_context(struct catpt_dev *cdev, struct dma_chan *chan)
|
|||
{
|
||||
struct catpt_stream_runtime *stream;
|
||||
|
||||
/* Lockless as no streams can be added or removed during D3 -> D0 transition. */
|
||||
list_for_each_entry(stream, &cdev->stream_list, node) {
|
||||
u32 off, size;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
|
||||
//
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
|
@ -97,12 +98,12 @@ catpt_get_stream_template(struct snd_pcm_substream *substream)
|
|||
return catpt_topology[type];
|
||||
}
|
||||
|
||||
/* Caller responsible for holding ->stream_mutex. */
|
||||
struct catpt_stream_runtime *
|
||||
catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
|
||||
{
|
||||
struct catpt_stream_runtime *pos, *result = NULL;
|
||||
|
||||
spin_lock(&cdev->list_lock);
|
||||
list_for_each_entry(pos, &cdev->stream_list, node) {
|
||||
if (pos->info.stream_hw_id == stream_hw_id) {
|
||||
result = pos;
|
||||
|
|
@ -110,7 +111,6 @@ catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
|
|||
}
|
||||
}
|
||||
|
||||
spin_unlock(&cdev->list_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -286,10 +286,6 @@ static int catpt_dai_startup(struct snd_pcm_substream *substream,
|
|||
INIT_LIST_HEAD(&stream->node);
|
||||
snd_soc_dai_set_dma_data(dai, substream, stream);
|
||||
|
||||
spin_lock(&cdev->list_lock);
|
||||
list_add_tail(&stream->node, &cdev->stream_list);
|
||||
spin_unlock(&cdev->list_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_request:
|
||||
|
|
@ -307,10 +303,6 @@ static void catpt_dai_shutdown(struct snd_pcm_substream *substream,
|
|||
|
||||
stream = snd_soc_dai_get_dma_data(dai, substream);
|
||||
|
||||
spin_lock(&cdev->list_lock);
|
||||
list_del(&stream->node);
|
||||
spin_unlock(&cdev->list_lock);
|
||||
|
||||
release_resource(stream->persistent);
|
||||
kfree(stream->persistent);
|
||||
catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask);
|
||||
|
|
@ -410,12 +402,15 @@ static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
|
|||
if (ret)
|
||||
return CATPT_IPC_RET(ret);
|
||||
|
||||
guard(mutex)(&cdev->stream_mutex);
|
||||
|
||||
ret = catpt_dai_apply_usettings(dai, stream);
|
||||
if (ret) {
|
||||
catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&stream->node, &cdev->stream_list);
|
||||
stream->allocated = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -430,6 +425,10 @@ static int catpt_dai_hw_free(struct snd_pcm_substream *substream,
|
|||
if (!stream->allocated)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&cdev->stream_mutex);
|
||||
list_del(&stream->node);
|
||||
mutex_unlock(&cdev->stream_mutex);
|
||||
|
||||
catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id);
|
||||
catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
|
||||
|
||||
|
|
@ -910,6 +909,8 @@ static int catpt_stream_volume_get(struct snd_kcontrol *kcontrol,
|
|||
int ret;
|
||||
int i;
|
||||
|
||||
guard(mutex)(&cdev->stream_mutex);
|
||||
|
||||
stream = catpt_stream_find(cdev, pin_id);
|
||||
if (!stream) {
|
||||
for (i = 0; i < CATPT_CHANNELS_MAX; i++)
|
||||
|
|
@ -941,6 +942,8 @@ static int catpt_stream_volume_put(struct snd_kcontrol *kcontrol,
|
|||
long *ctlvol = (long *)kcontrol->private_value;
|
||||
int ret, i;
|
||||
|
||||
guard(mutex)(&cdev->stream_mutex);
|
||||
|
||||
stream = catpt_stream_find(cdev, pin_id);
|
||||
if (!stream) {
|
||||
for (i = 0; i < CATPT_CHANNELS_MAX; i++)
|
||||
|
|
@ -1017,6 +1020,8 @@ static int catpt_loopback_switch_put(struct snd_kcontrol *kcontrol,
|
|||
bool mute;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&cdev->stream_mutex);
|
||||
|
||||
mute = (bool)ucontrol->value.integer.value[0];
|
||||
stream = catpt_stream_find(cdev, CATPT_PIN_ID_REFERENCE);
|
||||
if (!stream) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user