ipc: 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>
diff --git a/include/ipc/apr.h b/include/ipc/apr.h
index 4e5e3d8..6b4817e 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 @@
 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 fc1471d..aa53e21 100644
--- a/include/ipc/apr_tal.h
+++ b/include/ipc/apr_tal.h
@@ -74,7 +74,8 @@
 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 d202994..9f9cf91 100644
--- a/ipc/apr.c
+++ b/ipc/apr.c
@@ -775,6 +775,107 @@
 }
 
 /**
+ * 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 3803dcb..6683348 100644
--- a/ipc/apr_tal_glink.c
+++ b/ipc/apr_tal_glink.c
@@ -357,6 +357,38 @@
 	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;