diff options
author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-05-26 00:10:29 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-26 00:10:29 -0700 |
commit | 7d371c9315fe081fdf704d315e6994a71779b8e3 (patch) | |
tree | 4242475b8dd7a0618981c21c688d2d4041461ef5 /drivers/soc | |
parent | 5c161901b21e62b288ae31bd9c53d3eb2e134593 (diff) | |
parent | a3b6b4e493804e18d98f92e160978fd2634d7b84 (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.c | 85 | ||||
-rw-r--r-- | drivers/soc/qcom/glink_smem_native_xprt.c | 54 | ||||
-rw-r--r-- | drivers/soc/qcom/glink_xprt_if.h | 4 |
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, + ¶m); + 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, + ¶m); + 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. |