summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBanajit Goswami <bgoswami@codeaurora.org>2017-05-15 13:54:01 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2019-01-17 01:22:02 -0800
commit571090a2b3d1fdf8e01b0343d056d3c571b6bdb2 (patch)
tree7e8eb8927700503a55cd085bb211435ecbae75a6
parentfdf0731fd5fcc51bf1de5bb70600dca4585b2a4e (diff)
soc: q6dspv2: add api to vote for upgrading thread priority
For some time critical tasks, the thread priority might need to be upgraded to Real-Time Thread priority level. Expose an interface from APR layer so that clients can vote for a priority upgrade whenever needed. Change-Id: Ieb4afa914905750eccdf7672020a8751fdcf6462 Signed-off-by: Banajit Goswami <bgoswami@codeaurora.org> Signed-off-by: Soumya Managoli <smanag@codeaurora.org>
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr.c103
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c34
-rw-r--r--include/linux/qdsp6v2/apr.h4
-rw-r--r--include/linux/qdsp6v2/apr_tal.h10
4 files changed, 147 insertions, 4 deletions
diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c
index 8cd86915be98..9e55a25001ae 100644
--- a/drivers/soc/qcom/qdsp6v2/apr.c
+++ b/drivers/soc/qcom/qdsp6v2/apr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2014, 2016, 2018 The Linux Foundation.
+/* Copyright (c) 2010-2014, 2016, 2018-2019 The Linux Foundation.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -758,6 +758,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);
+
int apr_deregister(void *handle)
{
struct apr_svc *svc = handle;
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index 8a2be787b70e..f11787deac47 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017 The Linux Foundation.
+/* Copyright (c) 2016-2017, 2019 The Linux Foundation.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -358,6 +358,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;
diff --git a/include/linux/qdsp6v2/apr.h b/include/linux/qdsp6v2/apr.h
index 98432952f278..31c552b8da07 100644
--- a/include/linux/qdsp6v2/apr.h
+++ b/include/linux/qdsp6v2/apr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, 2019, 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
@@ -196,4 +196,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/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h
index 9b35c9f9882d..6100fe0b229c 100644
--- a/include/linux/qdsp6v2/apr_tal.h
+++ b/include/linux/qdsp6v2/apr_tal.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010-2011, 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011, 2016-2017, 2019 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
@@ -78,6 +79,9 @@ int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
#if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \
defined(CONFIG_MSM_QDSP6_APRV3_GLINK)
+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;
spinlock_t w_lock;
@@ -90,6 +94,10 @@ struct apr_svc_ch_dev {
bool if_remote_intent_ready;
};
#else
+static inline int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch)
+{ return 0; }
+static inline int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch) { return 0; }
+
struct apr_svc_ch_dev {
struct smd_channel *ch;
spinlock_t lock;