dsp: allocate contiguous memory for version information

Allocate contiguous memory for version information instead of splitting
it across the stack and heap to centralize memory and improve
readability.

CRs-Fixed: 2104576
Signed-off-by: Siena Richard <sienar@codeaurora.org>
Change-Id: Id7b5942522da6312da57bfef3d3c0b55934fe1d7
This commit is contained in:
Siena Richard 2017-09-05 11:15:45 -07:00
parent 8f7ccc2e6f
commit 2d0102dd44
4 changed files with 74 additions and 83 deletions

View file

@ -46,7 +46,7 @@ enum ver_query_status {
struct q6core_avcs_ver_info {
enum ver_query_status status;
struct avcs_fwk_ver_info ver_info;
struct avcs_fwk_ver_info *ver_info;
};
struct q6core_str {
@ -84,53 +84,40 @@ static struct generic_get_data_ *generic_get_data;
static int parse_fwk_version_info(uint32_t *payload)
{
size_t fwk_ver_size;
size_t svc_size;
size_t ver_size;
int num_services;
int ret = 0;
pr_debug("%s: Payload info num services %d\n",
__func__, payload[4]);
/*
* payload1[4] is the number of services running on DSP
* Based on this info, we copy the payload into core
* avcs version info structure.
*/
num_services = payload[4];
q6core_lcl.q6core_avcs_ver_info.ver_info.avcs_fwk_version.
num_services = num_services;
if (num_services > VSS_MAX_AVCS_NUM_SERVICES) {
pr_err("%s: num_services: %d greater than max services: %d\n",
__func__, num_services, VSS_MAX_AVCS_NUM_SERVICES);
ret = -EINVAL;
goto done;
return -EINVAL;
}
fwk_ver_size = sizeof(struct avcs_get_fwk_version);
svc_size = num_services * sizeof(struct avs_svc_api_info);
/*
* Dynamically allocate memory for all
* the services based on num_services
*/
q6core_lcl.q6core_avcs_ver_info.ver_info.services = NULL;
q6core_lcl.q6core_avcs_ver_info.ver_info.services =
kzalloc(svc_size, GFP_ATOMIC);
if (q6core_lcl.q6core_avcs_ver_info.ver_info.services == NULL) {
ret = -ENOMEM;
goto done;
}
/*
* memcpy is done twice because the memory allocated for
* q6core_lcl.q6core_avcs_ver_info.ver_info is not
* contiguous.
*/
memcpy(&q6core_lcl.q6core_avcs_ver_info.ver_info,
(uint8_t *)payload, fwk_ver_size);
memcpy(q6core_lcl.q6core_avcs_ver_info.ver_info.services,
(uint8_t *)&payload[sizeof(struct avcs_get_fwk_version)/
sizeof(uint32_t)], svc_size);
ret = 0;
done:
return ret;
ver_size = sizeof(struct avcs_get_fwk_version) +
num_services * sizeof(struct avs_svc_api_info);
if (q6core_lcl.q6core_avcs_ver_info.ver_info != NULL)
pr_warn("%s: Version info is not NULL\n", __func__);
q6core_lcl.q6core_avcs_ver_info.ver_info =
kzalloc(ver_size, GFP_ATOMIC);
if (q6core_lcl.q6core_avcs_ver_info.ver_info == NULL)
return -ENOMEM;
memcpy(q6core_lcl.q6core_avcs_ver_info.ver_info, (uint8_t *) payload,
ver_size);
return 0;
}
static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
@ -367,58 +354,56 @@ int q6core_get_service_version(uint32_t service_id,
struct avcs_fwk_ver_info *ver_info,
size_t size)
{
struct avcs_fwk_ver_info *cached_ver_info = NULL;
int i;
uint32_t num_services;
size_t svc_size;
svc_size = q6core_get_avcs_service_size(service_id);
if (svc_size != size) {
pr_err("%s: Expected size: %zu, Provided size: %zu\n",
__func__, svc_size, size);
return -EINVAL;
}
num_services =
q6core_lcl.q6core_avcs_ver_info.ver_info.
avcs_fwk_version.num_services;
size_t ver_size;
int ret;
if (ver_info == NULL) {
pr_err("%s: NULL parameter ver_info\n", __func__);
pr_err("%s: ver_info is NULL\n", __func__);
return -EINVAL;
}
memcpy(ver_info, &q6core_lcl.q6core_avcs_ver_info.
ver_info.avcs_fwk_version, sizeof(struct avcs_get_fwk_version));
if (service_id == AVCS_SERVICE_ID_ALL) {
memcpy(&ver_info->services[0], &q6core_lcl.
q6core_avcs_ver_info.ver_info.services[0],
(num_services * sizeof(struct avs_svc_api_info)));
} else {
for (i = 0; i < num_services; i++) {
if (q6core_lcl.q6core_avcs_ver_info.
ver_info.services[i].service_id == service_id) {
memcpy(&ver_info->services[0],
&q6core_lcl.q6core_avcs_ver_info.
ver_info.services[i], size);
break;
}
}
ret = q6core_get_fwk_version_size(service_id);
if (ret < 0) {
pr_err("%s: Failed to get service size for service id %d with error %d\n",
__func__, service_id, ret);
return ret;
}
return 0;
ver_size = ret;
if (ver_size != size) {
pr_err("%s: Expected size %zu and provided size %zu do not match\n",
__func__, ver_size, size);
return -EINVAL;
}
cached_ver_info = q6core_lcl.q6core_avcs_ver_info.ver_info;
num_services = cached_ver_info->avcs_fwk_version.num_services;
if (service_id == AVCS_SERVICE_ID_ALL) {
memcpy(ver_info, cached_ver_info, ver_size);
return 0;
}
ver_info->avcs_fwk_version = cached_ver_info->avcs_fwk_version;
for (i = 0; i < num_services; i++) {
if (cached_ver_info->services[i].service_id == service_id) {
ver_info->services[0] = cached_ver_info->services[i];
return 0;
}
}
pr_err("%s: No service matching service ID %d\n", __func__, service_id);
return -EINVAL;
}
EXPORT_SYMBOL(q6core_get_service_version);
size_t q6core_get_avcs_service_size(uint32_t service_id)
size_t q6core_get_fwk_version_size(uint32_t service_id)
{
int ret = 0;
uint32_t num_services;
num_services =
q6core_lcl.q6core_avcs_ver_info.ver_info.
avcs_fwk_version.num_services;
mutex_lock(&(q6core_lcl.ver_lock));
pr_debug("%s: q6core_avcs_ver_info.status(%d)\n", __func__,
q6core_lcl.q6core_avcs_ver_info.status);
@ -427,7 +412,6 @@ size_t q6core_get_avcs_service_size(uint32_t service_id)
case VER_QUERY_SUPPORTED:
pr_debug("%s: AVCS FWK version query already attempted\n",
__func__);
ret = num_services * sizeof(struct avs_svc_api_info);
break;
case VER_QUERY_UNSUPPORTED:
ret = -EOPNOTSUPP;
@ -436,9 +420,6 @@ size_t q6core_get_avcs_service_size(uint32_t service_id)
pr_debug("%s: Attempting AVCS FWK version query\n", __func__);
if (q6core_is_adsp_ready()) {
ret = q6core_send_get_avcs_fwk_ver_cmd();
if (ret == 0)
ret = num_services *
sizeof(struct avs_svc_api_info);
} else {
pr_err("%s: ADSP is not ready to query version\n",
__func__);
@ -453,12 +434,21 @@ size_t q6core_get_avcs_service_size(uint32_t service_id)
}
mutex_unlock(&(q6core_lcl.ver_lock));
if (service_id != AVCS_SERVICE_ID_ALL)
return sizeof(struct avs_svc_api_info);
if (ret)
goto done;
num_services = q6core_lcl.q6core_avcs_ver_info.ver_info
->avcs_fwk_version.num_services;
ret = sizeof(struct avcs_get_fwk_version);
if (service_id == AVCS_SERVICE_ID_ALL)
ret += num_services * sizeof(struct avs_svc_api_info);
else
ret += sizeof(struct avs_svc_api_info);
done:
return ret;
}
EXPORT_SYMBOL(q6core_get_avcs_service_size);
EXPORT_SYMBOL(q6core_get_fwk_version_size);
int32_t core_set_license(uint32_t key, uint32_t module_id)
{

View file

@ -4066,8 +4066,8 @@ static int voice_send_cvp_mfc_config_cmd(struct voice_data *v)
static int voice_get_avcs_version_per_service(uint32_t service_id)
{
int ret = 0;
size_t svc_size;
struct avcs_fwk_ver_info ver_info = {{0}, NULL};
size_t ver_size;
struct avcs_fwk_ver_info *ver_info = NULL;
if (service_id == AVCS_SERVICE_ID_ALL) {
pr_err("%s: Invalid service id: %d", __func__,
@ -4075,19 +4075,20 @@ static int voice_get_avcs_version_per_service(uint32_t service_id)
return -EINVAL;
}
svc_size = sizeof(struct avs_svc_api_info);
ver_info.services = kzalloc(svc_size, GFP_KERNEL);
if (ver_info.services == NULL)
ver_size = sizeof(struct avcs_get_fwk_version) +
sizeof(struct avs_svc_api_info);
ver_info = kzalloc(ver_size, GFP_KERNEL);
if (ver_info == NULL)
return -ENOMEM;
ret = q6core_get_service_version(service_id, &ver_info, svc_size);
ret = q6core_get_service_version(service_id, ver_info, ver_size);
if (ret < 0)
goto done;
ret = ver_info.services[0].api_version;
ret = ver_info->services[0].api_version;
common.is_avcs_version_queried = true;
done:
kfree(ver_info.services);
kfree(ver_info);
return ret;
}

View file

@ -9264,7 +9264,7 @@ struct avs_svc_api_info {
struct avcs_fwk_ver_info {
struct avcs_get_fwk_version avcs_fwk_version;
struct avs_svc_api_info *services;
struct avs_svc_api_info services[0];
} __packed;
/* LSM Specific */

View file

@ -25,7 +25,7 @@ bool q6core_is_adsp_ready(void);
int q6core_get_service_version(uint32_t service_id,
struct avcs_fwk_ver_info *ver_info,
size_t size);
size_t q6core_get_avcs_service_size(uint32_t service_id);
size_t q6core_get_fwk_version_size(uint32_t service_id);
#define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
#define DTS_EAGLE_LICENSE_ID 0x00028346