ASoC: SOF: ipc4-topology: Correct the allocation size for bytes controls

The size of the data behind of scontrol->ipc_control_data for bytes
controls is:
[1] sizeof(struct sof_ipc4_control_data) + // kernel only struct
[2] sizeof(struct sof_abi_hdr)) + payload

The max_size specifies the size of [2] and it is coming from topology.

Change the function to take this into account and allocate adequate amount
of memory behind scontrol->ipc_control_data.

With the change we will allocate [1] amount more memory to be able to hold
the full size of data.

Fixes: a382082ff7 ("ASoC: SOF: ipc4-topology: Add support for TPLG_CTL_BYTES")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://patch.msgid.link/20251217143945.2667-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Peter Ujfalusi 2025-12-17 16:39:39 +02:00 committed by Mark Brown
parent 2fa7471374
commit a653820700
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 27 additions and 8 deletions

View File

@ -2855,22 +2855,41 @@ static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_
struct sof_ipc4_msg *msg;
int ret;
if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) {
dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n",
/*
* The max_size is coming from topology and indicates the maximum size
* of sof_abi_hdr plus the payload, which excludes the local only
* 'struct sof_ipc4_control_data'
*/
if (scontrol->max_size < sizeof(struct sof_abi_hdr)) {
dev_err(sdev->dev,
"insufficient maximum size for a bytes control %s: %zu.\n",
scontrol->name, scontrol->max_size);
return -EINVAL;
}
if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) {
dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n",
scontrol->name, scontrol->priv_size,
scontrol->max_size - sizeof(*control_data));
if (scontrol->priv_size > scontrol->max_size) {
dev_err(sdev->dev,
"bytes control %s initial data size %zu exceeds max %zu.\n",
scontrol->name, scontrol->priv_size, scontrol->max_size);
return -EINVAL;
}
scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size;
if (scontrol->priv_size < sizeof(struct sof_abi_hdr)) {
dev_err(sdev->dev,
"bytes control %s initial data size %zu is insufficient.\n",
scontrol->name, scontrol->priv_size);
return -EINVAL;
}
scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
/*
* The used size behind the cdata pointer, which can be smaller than
* the maximum size
*/
scontrol->size = sizeof(*control_data) + scontrol->priv_size;
/* Allocate the cdata: local struct size + maximum payload size */
scontrol->ipc_control_data = kzalloc(sizeof(*control_data) + scontrol->max_size,
GFP_KERNEL);
if (!scontrol->ipc_control_data)
return -ENOMEM;