Unverified Commit a6538207 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown
Browse files

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: a382082f ("ASoC: SOF: ipc4-topology: Add support for TPLG_CTL_BYTES")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarSeppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://patch.msgid.link/20251217143945.2667-3-peter.ujfalusi@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2fa74713
Loading
Loading
Loading
Loading
+27 −8
Original line number Diff line number Diff line
@@ -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;