diff --git a/include/ipc/apr.h b/include/ipc/apr.h index 4e5e3d8630a5..6b4817edeeb5 100644 --- a/include/ipc/apr.h +++ b/include/ipc/apr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -188,4 +188,6 @@ int apr_set_q6_state(enum apr_subsys_state state); void apr_set_subsys_state(void); const char *apr_get_lpass_subsys_name(void); uint16_t apr_get_reset_domain(uint16_t proc); +int apr_start_rx_rt(void *handle); +int apr_end_rx_rt(void *handle); #endif diff --git a/include/ipc/apr_tal.h b/include/ipc/apr_tal.h index fc1471d4f08d..aa53e217c714 100644 --- a/include/ipc/apr_tal.h +++ b/include/ipc/apr_tal.h @@ -74,7 +74,8 @@ int apr_tal_close(struct apr_svc_ch_dev *apr_ch); int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch, int num_of_intents, uint32_t size); int apr_tal_init(void); - +int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch); +int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch); struct apr_svc_ch_dev { void *handle; diff --git a/ipc/apr.c b/ipc/apr.c index d2029943dcd9..9f9cf915ab3d 100644 --- a/ipc/apr.c +++ b/ipc/apr.c @@ -774,6 +774,107 @@ static void apr_reset_deregister(struct work_struct *work) kfree(apr_reset); } +/** + * apr_start_rx_rt - Clients call to vote for thread + * priority upgrade whenever needed. + * + * @handle: APR service handle + * + * Returns 0 on success or error otherwise. + */ +int apr_start_rx_rt(void *handle) +{ + int rc = 0; + struct apr_svc *svc = handle; + uint16_t dest_id = 0; + uint16_t client_id = 0; + + if (!svc) { + pr_err("%s: Invalid APR handle\n", __func__); + return -EINVAL; + } + + mutex_lock(&svc->m_lock); + dest_id = svc->dest_id; + client_id = svc->client_id; + + if ((client_id >= APR_CLIENT_MAX) || (dest_id >= APR_DEST_MAX)) { + pr_err("%s: %s invalid. client_id = %u, dest_id = %u\n", + __func__, + client_id >= APR_CLIENT_MAX ? "Client ID" : "Dest ID", + client_id, dest_id); + rc = -EINVAL; + goto exit; + } + + if (!client[dest_id][client_id].handle) { + pr_err("%s: Client handle is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + rc = apr_tal_start_rx_rt(client[dest_id][client_id].handle); + if (rc) + pr_err("%s: failed to set RT thread priority for APR RX. rc = %d\n", + __func__, rc); + +exit: + mutex_unlock(&svc->m_lock); + return rc; +} +EXPORT_SYMBOL(apr_start_rx_rt); + +/** + * apr_end_rx_rt - Clients call to unvote for thread + * priority upgrade (perviously voted with + * apr_start_rx_rt()). + * + * @handle: APR service handle + * + * Returns 0 on success or error otherwise. + */ +int apr_end_rx_rt(void *handle) +{ + int rc = 0; + struct apr_svc *svc = handle; + uint16_t dest_id = 0; + uint16_t client_id = 0; + + if (!svc) { + pr_err("%s: Invalid APR handle\n", __func__); + return -EINVAL; + } + + mutex_lock(&svc->m_lock); + dest_id = svc->dest_id; + client_id = svc->client_id; + + if ((client_id >= APR_CLIENT_MAX) || (dest_id >= APR_DEST_MAX)) { + pr_err("%s: %s invalid. client_id = %u, dest_id = %u\n", + __func__, + client_id >= APR_CLIENT_MAX ? "Client ID" : "Dest ID", + client_id, dest_id); + rc = -EINVAL; + goto exit; + } + + if (!client[dest_id][client_id].handle) { + pr_err("%s: Client handle is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + rc = apr_tal_end_rx_rt(client[dest_id][client_id].handle); + if (rc) + pr_err("%s: failed to reset RT thread priority for APR RX. rc = %d\n", + __func__, rc); + +exit: + mutex_unlock(&svc->m_lock); + return rc; +} +EXPORT_SYMBOL(apr_end_rx_rt); + /** * apr_deregister - Clients call to de-register * from APR. diff --git a/ipc/apr_tal_glink.c b/ipc/apr_tal_glink.c index 3803dcb1ea9a..6683348686aa 100644 --- a/ipc/apr_tal_glink.c +++ b/ipc/apr_tal_glink.c @@ -357,6 +357,38 @@ unlock: return rc ? NULL : apr_ch; } +int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch) +{ + int rc = 0; + + if (!apr_ch || !apr_ch->handle) { + rc = -EINVAL; + goto exit; + } + + mutex_lock(&apr_ch->m_lock); + rc = glink_start_rx_rt(apr_ch->handle); + mutex_unlock(&apr_ch->m_lock); +exit: + return rc; +} + +int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch) +{ + int rc = 0; + + if (!apr_ch || !apr_ch->handle) { + rc = -EINVAL; + goto exit; + } + + mutex_lock(&apr_ch->m_lock); + rc = glink_end_rx_rt(apr_ch->handle); + mutex_unlock(&apr_ch->m_lock); +exit: + return rc; +} + int apr_tal_close(struct apr_svc_ch_dev *apr_ch) { int rc;