summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/glink.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/glink.c')
-rw-r--r--drivers/soc/qcom/glink.c117
1 files changed, 50 insertions, 67 deletions
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 561b9074f2ee..e0d9f68ceef9 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -30,7 +30,6 @@
#include "glink_private.h"
#include "glink_xprt_if.h"
-#define GLINK_CTX_CANARY 0x58544324 /* "$CTX" */
/* Number of internal IPC Logging log pages */
#define NUM_LOG_PAGES 10
#define GLINK_PM_QOS_HOLDOFF_MS 10
@@ -40,7 +39,6 @@
#define GLINK_KTHREAD_PRIO 1
-static rwlock_t magic_lock;
/**
* struct glink_qos_priority_bin - Packet Scheduler's priority bucket
* @max_rate_kBps: Maximum rate supported by the priority bucket.
@@ -316,7 +314,6 @@ struct channel_ctx {
uint32_t rt_vote_on;
uint32_t rt_vote_off;
- uint32_t magic_number;
};
static struct glink_core_if core_impl;
@@ -447,33 +444,15 @@ static void glink_core_deinit_xprt_qos_cfg(
static int glink_get_ch_ctx(struct channel_ctx *ctx)
{
- unsigned long flags;
-
if (!ctx)
return -EINVAL;
- read_lock_irqsave(&magic_lock, flags);
- if (ctx->magic_number != GLINK_CTX_CANARY) {
- read_unlock_irqrestore(&magic_lock, flags);
- return -EINVAL;
- }
rwref_get(&ctx->ch_state_lhb2);
- read_unlock_irqrestore(&magic_lock, flags);
return 0;
}
-static int glink_put_ch_ctx(struct channel_ctx *ctx, bool update_magic)
+static void glink_put_ch_ctx(struct channel_ctx *ctx)
{
- unsigned long flags;
-
- if (!update_magic) {
- rwref_put(&ctx->ch_state_lhb2);
- return 0;
- }
- write_lock_irqsave(&magic_lock, flags);
- ctx->magic_number = 0;
rwref_put(&ctx->ch_state_lhb2);
- write_unlock_irqrestore(&magic_lock, flags);
- return 0;
}
/**
@@ -1935,13 +1914,14 @@ check_ctx:
kfree(flcid);
}
+ ctx->transport_ptr = xprt_ctx;
+ rwref_get(&ctx->ch_state_lhb2);
list_add_tail(&ctx->port_list_node, &xprt_ctx->channels);
GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx,
"%s: local:GLINK_CHANNEL_CLOSED\n",
__func__);
}
- rwref_get(&ctx->ch_state_lhb2);
spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
rwref_write_put(&xprt_ctx->xprt_state_lhb0);
mutex_lock(&xprt_ctx->xprt_dbgfs_lock_lhb4);
@@ -2623,7 +2603,6 @@ void *glink_open(const struct glink_open_config *cfg)
ctx->notify_tx_abort = cfg->notify_tx_abort;
ctx->notify_rx_tracer_pkt = cfg->notify_rx_tracer_pkt;
ctx->notify_remote_rx_intent = cfg->notify_remote_rx_intent;
- ctx->magic_number = GLINK_CTX_CANARY;
if (!ctx->notify_rx_intent_req)
ctx->notify_rx_intent_req = glink_dummy_notify_rx_intent_req;
@@ -2640,7 +2619,6 @@ void *glink_open(const struct glink_open_config *cfg)
ctx->local_xprt_req = best_id;
ctx->no_migrate = cfg->transport &&
!(cfg->options & GLINK_OPT_INITIAL_XPORT);
- ctx->transport_ptr = transport_ptr;
ctx->local_open_state = GLINK_CHANNEL_OPENING;
GLINK_INFO_PERF_CH(ctx,
"%s: local:GLINK_CHANNEL_CLOSED->GLINK_CHANNEL_OPENING\n",
@@ -2764,13 +2742,13 @@ int glink_close(void *handle)
GLINK_INFO_CH(ctx, "%s: Closing channel, ctx: %p\n", __func__, ctx);
if (ctx->local_open_state == GLINK_CHANNEL_CLOSED) {
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return 0;
}
if (ctx->local_open_state == GLINK_CHANNEL_CLOSING) {
/* close already pending */
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
@@ -2835,7 +2813,7 @@ relock: xprt_ctx = ctx->transport_ptr;
rwref_put(&ctx->ch_state_lhb2);
rwref_read_put(&xprt_ctx->xprt_state_lhb0);
- glink_put_ch_ctx(ctx, true);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_close);
@@ -2884,7 +2862,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
struct channel_ctx *ctx = (struct channel_ctx *)handle;
uint32_t riid;
int ret = 0;
- struct glink_core_tx_pkt *tx_info;
+ struct glink_core_tx_pkt *tx_info = NULL;
size_t intent_size;
bool is_atomic =
tx_flags & (GLINK_TX_SINGLE_THREADED | GLINK_TX_ATOMIC);
@@ -2899,6 +2877,13 @@ static int glink_tx_common(void *handle, void *pkt_priv,
return ret;
rwref_read_get_atomic(&ctx->ch_state_lhb2, is_atomic);
+ tx_info = kzalloc(sizeof(struct glink_core_tx_pkt),
+ is_atomic ? GFP_ATOMIC : GFP_KERNEL);
+ if (!tx_info) {
+ GLINK_ERR_CH(ctx, "%s: No memory for allocation\n", __func__);
+ ret = -ENOMEM;
+ goto glink_tx_common_err;
+ }
if (!(vbuf_provider || pbuf_provider)) {
ret = -EINVAL;
goto glink_tx_common_err;
@@ -3018,14 +3003,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
GLINK_INFO_PERF_CH(ctx, "%s: R[%u]:%zu data[%p], size[%zu]. TID %u\n",
__func__, riid, intent_size,
data ? data : iovec, size, current->pid);
- tx_info = kzalloc(sizeof(struct glink_core_tx_pkt),
- is_atomic ? GFP_ATOMIC : GFP_KERNEL);
- if (!tx_info) {
- GLINK_ERR_CH(ctx, "%s: No memory for allocation\n", __func__);
- ch_push_remote_rx_intent(ctx, intent_size, riid, cookie);
- ret = -ENOMEM;
- goto glink_tx_common_err;
- }
+
rwref_lock_init(&tx_info->pkt_ref, glink_tx_pkt_release);
INIT_LIST_HEAD(&tx_info->list_done);
INIT_LIST_HEAD(&tx_info->list_node);
@@ -3050,10 +3028,15 @@ static int glink_tx_common(void *handle, void *pkt_priv,
else
xprt_schedule_tx(ctx->transport_ptr, ctx, tx_info);
+ rwref_read_put(&ctx->ch_state_lhb2);
+ glink_put_ch_ctx(ctx);
+ return ret;
+
glink_tx_common_err:
rwref_read_put(&ctx->ch_state_lhb2);
glink_tx_common_err_2:
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
+ kfree(tx_info);
return ret;
}
@@ -3102,7 +3085,7 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size)
/* Can only queue rx intents if channel is fully opened */
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
@@ -3111,14 +3094,14 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size)
GLINK_ERR_CH(ctx,
"%s: Intent pointer allocation failed size[%zu]\n",
__func__, size);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -ENOMEM;
}
GLINK_DBG_CH(ctx, "%s: L[%u]:%zu\n", __func__, intent_ptr->id,
intent_ptr->intent_size);
if (ctx->transport_ptr->capabilities & GCAP_INTENTLESS) {
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
@@ -3128,7 +3111,7 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size)
if (ret)
/* unable to transmit, dequeue intent */
ch_remove_local_rx_intent(ctx, intent_ptr->id);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_queue_rx_intent);
@@ -3160,12 +3143,12 @@ bool glink_rx_intent_exists(void *handle, size_t size)
if (size <= intent->intent_size) {
spin_unlock_irqrestore(
&ctx->local_rx_intent_lst_lock_lhc1, flags);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return true;
}
}
spin_unlock_irqrestore(&ctx->local_rx_intent_lst_lock_lhc1, flags);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return false;
}
EXPORT_SYMBOL(glink_rx_intent_exists);
@@ -3194,7 +3177,7 @@ int glink_rx_done(void *handle, const void *ptr, bool reuse)
if (IS_ERR_OR_NULL(liid_ptr)) {
/* invalid pointer */
GLINK_ERR_CH(ctx, "%s: Invalid pointer %p\n", __func__, ptr);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EINVAL;
}
@@ -3220,7 +3203,7 @@ int glink_rx_done(void *handle, const void *ptr, bool reuse)
/* send rx done */
ctx->transport_ptr->ops->tx_cmd_local_rx_done(ctx->transport_ptr->ops,
ctx->lcid, id, reuse);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_rx_done);
@@ -3274,7 +3257,7 @@ int glink_sigs_set(void *handle, uint32_t sigs)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
@@ -3284,7 +3267,7 @@ int glink_sigs_set(void *handle, uint32_t sigs)
ctx->lcid, ctx->lsigs);
GLINK_INFO_CH(ctx, "%s: Sent SIGNAL SET command\n", __func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_sigs_set);
@@ -3310,12 +3293,12 @@ int glink_sigs_local_get(void *handle, uint32_t *sigs)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
*sigs = ctx->lsigs;
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return 0;
}
EXPORT_SYMBOL(glink_sigs_local_get);
@@ -3342,12 +3325,12 @@ int glink_sigs_remote_get(void *handle, uint32_t *sigs)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
*sigs = ctx->rsigs;
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return 0;
}
EXPORT_SYMBOL(glink_sigs_remote_get);
@@ -3452,7 +3435,7 @@ int glink_qos_latency(void *handle, unsigned long latency_us, size_t pkt_size)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
@@ -3462,7 +3445,7 @@ int glink_qos_latency(void *handle, unsigned long latency_us, size_t pkt_size)
if (ret < 0)
GLINK_ERR_CH(ctx, "%s: QoS %lu:%zu cannot be met\n",
__func__, latency_us, pkt_size);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_qos_latency);
@@ -3486,12 +3469,12 @@ int glink_qos_cancel(void *handle)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
ret = glink_qos_reset_priority(ctx);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_qos_cancel);
@@ -3518,7 +3501,7 @@ int glink_qos_start(void *handle)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EBUSY;
}
@@ -3527,7 +3510,7 @@ int glink_qos_start(void *handle)
ret = glink_qos_add_ch_tx_intent(ctx);
spin_unlock(&ctx->tx_lists_lock_lhc3);
spin_unlock_irqrestore(&ctx->transport_ptr->tx_ready_lock_lhb3, flags);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ret;
}
EXPORT_SYMBOL(glink_qos_start);
@@ -3555,11 +3538,11 @@ unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return (unsigned long)-EBUSY;
}
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ctx->transport_ptr->ops->get_power_vote_ramp_time(
ctx->transport_ptr->ops,
glink_prio_to_power_state(ctx->transport_ptr,
@@ -3585,13 +3568,13 @@ int glink_start_rx_rt(void *handle)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
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);
+ glink_put_ch_ctx(ctx);
return ret;
}
@@ -3612,13 +3595,13 @@ int glink_end_rx_rt(void *handle)
if (!ch_is_fully_opened(ctx)) {
GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
__func__);
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
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);
+ glink_put_ch_ctx(ctx);
return ret;
}
@@ -3704,10 +3687,10 @@ int glink_wait_link_down(void *handle)
if (ret)
return ret;
if (!ctx->transport_ptr) {
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return -EOPNOTSUPP;
}
- glink_put_ch_ctx(ctx, false);
+ glink_put_ch_ctx(ctx);
return ctx->transport_ptr->ops->wait_link_down(ctx->transport_ptr->ops);
}
EXPORT_SYMBOL(glink_wait_link_down);
@@ -4143,6 +4126,7 @@ static void glink_core_link_down(struct glink_transport_if *if_ptr)
rwref_write_get(&xprt_ptr->xprt_state_lhb0);
xprt_ptr->next_lcid = 1;
xprt_ptr->local_state = GLINK_XPRT_DOWN;
+ xprt_ptr->curr_qos_rate_kBps = 0;
xprt_ptr->local_version_idx = xprt_ptr->versions_entries - 1;
xprt_ptr->remote_version_idx = xprt_ptr->versions_entries - 1;
xprt_ptr->l_features =
@@ -6248,7 +6232,6 @@ EXPORT_SYMBOL(glink_get_xprt_log_ctx);
static int glink_init(void)
{
log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "glink", 0);
- rwlock_init(&magic_lock);
if (!log_ctx)
GLINK_ERR("%s: unable to create log context\n", __func__);
glink_debugfs_init();