plugins: tinyalsa: use different get_param_payload per pcm_id
If two sessions calls get_param mixer control concurrently, it
can free the payload while other session is accessing it. Make
get_param_payload per pcm_id to handle concurrent get_param call.
Change-Id: Ia6f8b162a64666e945d9520c10267408d38a74b7
diff --git a/plugins/tinyalsa/src/agm_mixer_plugin.c b/plugins/tinyalsa/src/agm_mixer_plugin.c
index 1d95750..2c69c27 100644
--- a/plugins/tinyalsa/src/agm_mixer_plugin.c
+++ b/plugins/tinyalsa/src/agm_mixer_plugin.c
@@ -1,5 +1,6 @@
/*
** Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
@@ -146,6 +147,11 @@
"datapathParams",
};
+struct amp_get_param_info {
+ void *get_param_payload;
+ int get_param_payload_size;
+};
+
struct amp_dev_info {
char **names;
int *idx_arr;
@@ -165,8 +171,7 @@
* "pcm<id> getParam"
* Unused for BE devs
*/
- void *get_param_payload;
- int get_param_payload_size;
+ struct amp_get_param_info *get_param_info;
};
struct amp_be_group_info {
@@ -264,9 +269,9 @@
adi->pcm_mtd_ctl = NULL;
}
- if (adi->get_param_payload) {
- free(adi->get_param_payload);
- adi->get_param_payload = NULL;
+ if (adi->get_param_info) {
+ free(adi->get_param_info);
+ adi->get_param_info = NULL;
}
adi->count = 0;
@@ -1289,9 +1294,9 @@
struct snd_control *ctl, struct snd_ctl_tlv *tlv)
{
struct amp_dev_info *pcm_adi = ctl->private_data;
-
void *payload;
- int pcm_idx = ctl->private_value;
+ int pcm_idx;
+ int idx = ctl->private_value;
int ret = 0;
size_t tlv_size;
@@ -1299,18 +1304,20 @@
payload = &tlv->tlv[0];
tlv_size = tlv->length;
+ pcm_idx = pcm_adi->idx_arr[idx];
- if (!pcm_adi->get_param_payload) {
+ if (!pcm_adi->get_param_info[idx].get_param_payload) {
AGM_LOGE("%s: put() for getParam not called\n", __func__);
return -EINVAL;
}
- if (tlv_size < pcm_adi->get_param_payload_size) {
+ if (tlv_size < pcm_adi->get_param_info[idx].get_param_payload_size) {
AGM_LOGE("%s: Buffer size less than expected\n", __func__);
return -EINVAL;
}
- memcpy(payload, pcm_adi->get_param_payload, pcm_adi->get_param_payload_size);
+ memcpy(payload, pcm_adi->get_param_info[idx].get_param_payload,
+ pcm_adi->get_param_info[idx].get_param_payload_size);
ret = agm_session_get_params(pcm_idx, payload, tlv_size);
if (ret == -EALREADY)
@@ -1319,9 +1326,9 @@
if (ret)
AGM_LOGE("%s: failed err %d for %s\n", __func__, ret, ctl->name);
- free(pcm_adi->get_param_payload);
- pcm_adi->get_param_payload = NULL;
- pcm_adi->get_param_payload_size = 0;
+ free(pcm_adi->get_param_info[idx].get_param_payload);
+ pcm_adi->get_param_info[idx].get_param_payload = NULL;
+ pcm_adi->get_param_info[idx].get_param_payload_size = 0;
return ret;
}
@@ -1329,22 +1336,25 @@
struct snd_control *ctl, struct snd_ctl_tlv *tlv)
{
struct amp_dev_info *pcm_adi = ctl->private_data;
+ int idx = ctl->private_value;
void *payload;
AGM_LOGV("%s: enter\n", __func__);
- if (pcm_adi->get_param_payload) {
- free(pcm_adi->get_param_payload);
- pcm_adi->get_param_payload = NULL;
+ if (pcm_adi->get_param_info[idx].get_param_payload) {
+ free(pcm_adi->get_param_info[idx].get_param_payload);
+ pcm_adi->get_param_info[idx].get_param_payload = NULL;
}
payload = &tlv->tlv[0];
- pcm_adi->get_param_payload_size = tlv->length;
+ pcm_adi->get_param_info[idx].get_param_payload_size = tlv->length;
- pcm_adi->get_param_payload = calloc(1, pcm_adi->get_param_payload_size);
- if (!pcm_adi->get_param_payload)
+ pcm_adi->get_param_info[idx].get_param_payload = calloc(1,
+ pcm_adi->get_param_info[idx].get_param_payload_size);
+ if (!pcm_adi->get_param_info[idx].get_param_payload)
return -ENOMEM;
- memcpy(pcm_adi->get_param_payload, payload, pcm_adi->get_param_payload_size);
+ memcpy(pcm_adi->get_param_info[idx].get_param_payload, payload,
+ pcm_adi->get_param_info[idx].get_param_payload_size);
return 0;
}
@@ -1873,6 +1883,12 @@
if (!pcm_adi->pcm_mtd_ctl)
return -ENOMEM;
+ pcm_adi->get_param_info = (struct amp_get_param_info *)calloc(pcm_adi->count, sizeof(struct amp_get_param_info));
+ if (!pcm_adi->get_param_info) {
+ free(pcm_adi->pcm_mtd_ctl);
+ return -ENOMEM;
+ }
+
for (i = 1; i < pcm_adi->count; i++) {
char *name = pcm_adi->names[i];
int idx = pcm_adi->idx_arr[i];
@@ -1897,7 +1913,7 @@
amp_create_pcm_calibration_ctl(amp_priv, name, (*ctl_idx)++,
idx, pcm_adi);
amp_create_pcm_get_param_ctl(amp_priv, name, (*ctl_idx)++,
- idx, pcm_adi);
+ i, pcm_adi);
amp_create_pcm_bufinfo_ctl(amp_priv, name, (*ctl_idx)++,
idx, pcm_adi);
}