Skip to content

Commit 863893c

Browse files
committed
ASoC: SOF: ipc4-control: pass data pointer and size as function arguments
Move the data_ptr and data_size assignments into sof_ipc4_set_get_kcontrol_data() as explicit function parameters instead of having each caller set and clear them on the shared cdata->msg before and after the call. Link: #5734 Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 71c6be1 commit 863893c

1 file changed

Lines changed: 36 additions & 44 deletions

File tree

sound/soc/sof/ipc4-control.c

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
#include "ipc4-topology.h"
1414

1515
static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol,
16-
bool set, bool lock)
16+
bool set, bool lock,
17+
void *data_ptr, size_t data_size)
1718
{
1819
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
1920
struct snd_soc_component *scomp = scontrol->scomp;
@@ -50,6 +51,14 @@ static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol,
5051
if (!swidget->use_count)
5152
goto unlock;
5253

54+
/*
55+
* Set the data pointer and size on the msg under the mutex to prevent
56+
* concurrent callers (e.g. widget setup vs userspace volume_put) from
57+
* overwriting each other's data fields on the shared cdata->msg.
58+
*/
59+
msg->data_ptr = data_ptr;
60+
msg->data_size = data_size;
61+
5362
msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK;
5463
msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id);
5564

@@ -60,7 +69,7 @@ static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol,
6069
/* It is a set-data operation, and we have a valid backup that we can restore */
6170
if (ret < 0) {
6271
if (!scontrol->old_ipc_control_data)
63-
goto unlock;
72+
goto clear;
6473
/*
6574
* Current ipc_control_data is not valid, we use the last known good
6675
* configuration
@@ -69,12 +78,21 @@ static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol,
6978
scontrol->size);
7079
kfree(scontrol->old_ipc_control_data);
7180
scontrol->old_ipc_control_data = NULL;
81+
/*
82+
* The memcpy above overwrites cdata->msg, restore the data
83+
* fields from the function arguments for the retry.
84+
*/
85+
msg->data_ptr = data_ptr;
86+
msg->data_size = data_size;
7287
/* Send the last known good configuration to firmware */
7388
ret = iops->set_get_data(sdev, msg, msg->data_size, set);
74-
if (ret < 0)
75-
goto unlock;
7689
}
7790

91+
clear:
92+
/* Clear data fields for set operations to avoid dangling pointers */
93+
msg->data_ptr = NULL;
94+
msg->data_size = 0;
95+
7896
unlock:
7997
if (lock)
8098
mutex_unlock(&swidget->setup_mutex);
@@ -88,7 +106,6 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
88106
{
89107
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
90108
struct sof_ipc4_gain *gain = swidget->private;
91-
struct sof_ipc4_msg *msg = &cdata->msg;
92109
struct sof_ipc4_gain_params params;
93110
bool all_channels_equal = true;
94111
u32 value;
@@ -121,12 +138,8 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
121138
params.curve_duration_h = gain->data.params.curve_duration_h;
122139
params.curve_type = gain->data.params.curve_type;
123140

124-
msg->data_ptr = &params;
125-
msg->data_size = sizeof(params);
126-
127-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
128-
msg->data_ptr = NULL;
129-
msg->data_size = 0;
141+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock,
142+
&params, sizeof(params));
130143
if (ret < 0) {
131144
dev_err(sdev->dev, "Failed to set volume update for %s\n",
132145
scontrol->name);
@@ -208,7 +221,6 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev,
208221
{
209222
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
210223
struct sof_ipc4_control_msg_payload *data;
211-
struct sof_ipc4_msg *msg = &cdata->msg;
212224
size_t data_size;
213225
unsigned int i;
214226
int ret;
@@ -225,12 +237,8 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev,
225237
data->chanv[i].value = cdata->chanv[i].value;
226238
}
227239

228-
msg->data_ptr = data;
229-
msg->data_size = data_size;
230-
231-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
232-
msg->data_ptr = NULL;
233-
msg->data_size = 0;
240+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock,
241+
data, data_size);
234242
if (ret < 0)
235243
dev_err(sdev->dev, "Failed to set control update for %s\n",
236244
scontrol->name);
@@ -245,7 +253,6 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol)
245253
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
246254
struct snd_soc_component *scomp = scontrol->scomp;
247255
struct sof_ipc4_control_msg_payload *data;
248-
struct sof_ipc4_msg *msg = &cdata->msg;
249256
size_t data_size;
250257
unsigned int i;
251258
int ret;
@@ -263,13 +270,10 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol)
263270

264271
data->id = cdata->index;
265272
data->num_elems = scontrol->num_channels;
266-
msg->data_ptr = data;
267-
msg->data_size = data_size;
268273

269274
scontrol->comp_data_dirty = false;
270-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, true);
271-
msg->data_ptr = NULL;
272-
msg->data_size = 0;
275+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, true,
276+
data, data_size);
273277
if (!ret) {
274278
for (i = 0; i < scontrol->num_channels; i++) {
275279
cdata->chanv[i].channel = data->chanv[i].channel;
@@ -306,12 +310,8 @@ sof_ipc4_set_bytes_control_data(struct snd_sof_control *scontrol, bool lock)
306310

307311
msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
308312

309-
msg->data_ptr = msg_data;
310-
msg->data_size = data_size;
311-
312-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
313-
msg->data_ptr = NULL;
314-
msg->data_size = 0;
313+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock,
314+
msg_data, data_size);
315315
if (ret < 0)
316316
dev_err(scomp->dev, "%s: Failed to set control update for %s\n",
317317
__func__, scontrol->name);
@@ -351,11 +351,9 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock)
351351
msg_data->id = cdata->index;
352352
msg_data->num_elems = 0; /* ignored for bytes */
353353

354-
msg->data_ptr = msg_data;
355-
msg->data_size = data_size;
356-
357354
scontrol->comp_data_dirty = false;
358-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock);
355+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock,
356+
msg_data, data_size);
359357
if (!ret) {
360358
if (msg->data_size > scontrol->max_size - sizeof(*data)) {
361359
dev_err(scomp->dev,
@@ -532,13 +530,10 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev,
532530

533531
msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
534532

535-
msg->data_ptr = data->data;
536-
if (set)
537-
msg->data_size = data->size;
538-
else
539-
msg->data_size = scontrol->max_size - sizeof(*data);
540-
541-
ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock);
533+
ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock,
534+
data->data,
535+
set ? data->size :
536+
scontrol->max_size - sizeof(*data));
542537
if (ret < 0) {
543538
dev_err(sdev->dev, "Failed to %s for %s\n",
544539
set ? "set bytes update" : "get bytes",
@@ -549,9 +544,6 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev,
549544
scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size;
550545
}
551546

552-
msg->data_ptr = NULL;
553-
msg->data_size = 0;
554-
555547
return ret;
556548
}
557549

0 commit comments

Comments
 (0)