From 2d0102dd44b605c9ae24dd93e49b9de7811fffe4 Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Tue, 5 Sep 2017 11:15:45 -0700 Subject: [PATCH] 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 Change-Id: Id7b5942522da6312da57bfef3d3c0b55934fe1d7 --- dsp/q6core.c | 136 +++++++++++++++++-------------------- dsp/q6voice.c | 17 ++--- include/dsp/apr_audio-v2.h | 2 +- include/dsp/q6core.h | 2 +- 4 files changed, 74 insertions(+), 83 deletions(-) diff --git a/dsp/q6core.c b/dsp/q6core.c index 8d82704055..72c146b023 100644 --- a/dsp/q6core.c +++ b/dsp/q6core.c @@ -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) { diff --git a/dsp/q6voice.c b/dsp/q6voice.c index 7cd340f961..fa338b2282 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -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; } diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 2256b7b4d9..121efc432c 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -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 */ diff --git a/include/dsp/q6core.h b/include/dsp/q6core.h index 1f1adad031..f6240a33e6 100644 --- a/include/dsp/q6core.h +++ b/include/dsp/q6core.h @@ -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