summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-05-26 00:10:29 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-26 00:10:29 -0700
commit7d371c9315fe081fdf704d315e6994a71779b8e3 (patch)
tree4242475b8dd7a0618981c21c688d2d4041461ef5 /drivers/soc
parent5c161901b21e62b288ae31bd9c53d3eb2e134593 (diff)
parenta3b6b4e493804e18d98f92e160978fd2634d7b84 (diff)
Merge "soc: qcom: glink: Add new APIs to toggle RX thread priority"
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/glink.c85
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c54
-rw-r--r--drivers/soc/qcom/glink_xprt_if.h4
3 files changed, 141 insertions, 2 deletions
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 72f5829d1eb6..561b9074f2ee 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -232,7 +232,9 @@ static DEFINE_MUTEX(edge_list_lock_lhd0);
* @req_rate_kBps: Current QoS request by the channel.
* @tx_intent_cnt: Intent count to transmit soon in future.
* @tx_cnt: Packets to be picked by tx scheduler.
- */
+ * @rt_vote_on: Number of times RT vote on is called.
+ * @rt_vote_off: Number of times RT vote off is called.
+*/
struct channel_ctx {
struct rwref_lock ch_state_lhb2;
struct list_head port_list_node;
@@ -311,6 +313,9 @@ struct channel_ctx {
unsigned long req_rate_kBps;
uint32_t tx_intent_cnt;
uint32_t tx_cnt;
+
+ uint32_t rt_vote_on;
+ uint32_t rt_vote_off;
uint32_t magic_number;
};
@@ -2418,6 +2423,25 @@ static int dummy_power_unvote(struct glink_transport_if *if_ptr)
}
/**
+ * dummy_rx_rt_vote() - Dummy RX Realtime thread vote
+ * @if_ptr: The transport to transmit on.
+
+ */
+static int dummy_rx_rt_vote(struct glink_transport_if *if_ptr)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * dummy_rx_rt_unvote() - Dummy RX Realtime thread unvote
+ * @if_ptr: The transport to transmit on.
+ */
+static int dummy_rx_rt_unvote(struct glink_transport_if *if_ptr)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
* notif_if_up_all_xprts() - Check and notify existing transport state if up
* @notif_info: Data structure containing transport information to be notified.
*
@@ -3543,6 +3567,61 @@ unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size)
}
EXPORT_SYMBOL(glink_qos_get_ramp_time);
+
+/**
+ * glink_start_rx_rt() - Vote for RT thread priority on RX.
+ * @handle: Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_start_rx_rt(void *handle)
+{
+ struct channel_ctx *ctx = (struct channel_ctx *)handle;
+ int ret;
+
+ ret = glink_get_ch_ctx(ctx);
+ if (ret)
+ return ret;
+ if (!ch_is_fully_opened(ctx)) {
+ GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
+ __func__);
+ glink_put_ch_ctx(ctx, false);
+ return -EBUSY;
+ }
+ ret = ctx->transport_ptr->ops->rx_rt_vote(ctx->transport_ptr->ops);
+ ctx->rt_vote_on++;
+ GLINK_INFO_CH(ctx, "%s: Voting RX Realtime Thread %d", __func__, ret);
+ glink_put_ch_ctx(ctx, false);
+ return ret;
+}
+
+/**
+ * glink_end_rx_rt() - Vote for RT thread priority on RX.
+ * @handle: Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_end_rx_rt(void *handle)
+{
+ struct channel_ctx *ctx = (struct channel_ctx *)handle;
+ int ret;
+
+ ret = glink_get_ch_ctx(ctx);
+ if (ret)
+ return ret;
+ if (!ch_is_fully_opened(ctx)) {
+ GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
+ __func__);
+ glink_put_ch_ctx(ctx, false);
+ return -EBUSY;
+ }
+ ret = ctx->transport_ptr->ops->rx_rt_unvote(ctx->transport_ptr->ops);
+ ctx->rt_vote_off++;
+ GLINK_INFO_CH(ctx, "%s: Unvoting RX Realtime Thread %d", __func__, ret);
+ glink_put_ch_ctx(ctx, false);
+ return ret;
+}
+
/**
* glink_rpm_rx_poll() - Poll and receive any available events
* @handle: Channel handle in which this operation is performed.
@@ -3950,6 +4029,10 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr,
if_ptr->power_vote = dummy_power_vote;
if (!if_ptr->power_unvote)
if_ptr->power_unvote = dummy_power_unvote;
+ if (!if_ptr->rx_rt_vote)
+ if_ptr->rx_rt_vote = dummy_rx_rt_vote;
+ if (!if_ptr->rx_rt_unvote)
+ if_ptr->rx_rt_unvote = dummy_rx_rt_unvote;
xprt_ptr->capabilities = 0;
xprt_ptr->ops = if_ptr;
spin_lock_init(&xprt_ptr->xprt_ctx_lock_lhb1);
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 3f969234b705..168db46084df 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -182,6 +182,8 @@ struct mailbox_config_info {
* @deferred_cmds: List of deferred commands that need to be
* processed in process context.
* @deferred_cmds_cnt: Number of deferred commands in queue.
+ * @rt_vote_lock: Serialize access to RT rx votes
+ * @rt_votes: Vote count for RT rx thread priority
* @num_pw_states: Size of @ramp_time_us.
* @ramp_time_us: Array of ramp times in microseconds where array
* index position represents a power state.
@@ -221,6 +223,8 @@ struct edge_info {
spinlock_t rx_lock;
struct list_head deferred_cmds;
uint32_t deferred_cmds_cnt;
+ spinlock_t rt_vote_lock;
+ uint32_t rt_votes;
uint32_t num_pw_states;
unsigned long *ramp_time_us;
struct mailbox_config_info *mailbox;
@@ -2093,6 +2097,52 @@ static int power_unvote(struct glink_transport_if *if_ptr)
}
/**
+ * rx_rt_vote() - Increment and RX thread RT vote
+ * @if_ptr: The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int rx_rt_vote(struct glink_transport_if *if_ptr)
+{
+ struct edge_info *einfo;
+ struct sched_param param = { .sched_priority = 1 };
+ int ret = 0;
+ unsigned long flags;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->rt_vote_lock, flags);
+ if (!einfo->rt_votes)
+ ret = sched_setscheduler_nocheck(einfo->task, SCHED_FIFO,
+ &param);
+ einfo->rt_votes++;
+ spin_unlock_irqrestore(&einfo->rt_vote_lock, flags);
+ return ret;
+}
+
+/**
+ * rx_rt_unvote() - Remove a RX thread RT vote
+ * @if_ptr: The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int rx_rt_unvote(struct glink_transport_if *if_ptr)
+{
+ struct edge_info *einfo;
+ struct sched_param param = { .sched_priority = 0 };
+ int ret = 0;
+ unsigned long flags;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->rt_vote_lock, flags);
+ einfo->rt_votes--;
+ if (!einfo->rt_votes)
+ ret = sched_setscheduler_nocheck(einfo->task, SCHED_NORMAL,
+ &param);
+ spin_unlock_irqrestore(&einfo->rt_vote_lock, flags);
+ return ret;
+}
+
+/**
* negotiate_features_v1() - determine what features of a version can be used
* @if_ptr: The transport for which features are negotiated for.
* @version: The version negotiated.
@@ -2137,6 +2187,8 @@ static void init_xprt_if(struct edge_info *einfo)
einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
einfo->xprt_if.power_vote = power_vote;
einfo->xprt_if.power_unvote = power_unvote;
+ einfo->xprt_if.rx_rt_vote = rx_rt_vote;
+ einfo->xprt_if.rx_rt_unvote = rx_rt_unvote;
}
/**
@@ -2310,6 +2362,8 @@ static int glink_smem_native_probe(struct platform_device *pdev)
init_srcu_struct(&einfo->use_ref);
spin_lock_init(&einfo->rx_lock);
INIT_LIST_HEAD(&einfo->deferred_cmds);
+ spin_lock_init(&einfo->rt_vote_lock);
+ einfo->rt_votes = 0;
mutex_lock(&probe_lock);
if (edge_infos[einfo->remote_proc_id]) {
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index f4d5a3b303db..47c15807e379 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -141,6 +141,8 @@ struct glink_transport_if {
struct glink_transport_if *if_ptr, uint32_t state);
int (*power_vote)(struct glink_transport_if *if_ptr, uint32_t state);
int (*power_unvote)(struct glink_transport_if *if_ptr);
+ int (*rx_rt_vote)(struct glink_transport_if *if_ptr);
+ int (*rx_rt_unvote)(struct glink_transport_if *if_ptr);
/*
* Keep data pointers at the end of the structure after all function
* pointer to allow for in-place initialization.