Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a92a897e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: glink: Remove magic number logic"

parents 106f4889 8c838487
Loading
Loading
Loading
Loading
+113 −53
Original line number Diff line number Diff line
@@ -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.
@@ -232,6 +230,8 @@ 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;
@@ -312,7 +312,9 @@ struct channel_ctx {
	unsigned long req_rate_kBps;
	uint32_t tx_intent_cnt;
	uint32_t tx_cnt;
	uint32_t magic_number;

	uint32_t rt_vote_on;
	uint32_t rt_vote_off;
};

static struct glink_core_if core_impl;
@@ -443,33 +445,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;
}

/**
@@ -2418,6 +2402,25 @@ static int dummy_power_unvote(struct glink_transport_if *if_ptr)
	return -EOPNOTSUPP;
}

/**
 * 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.
@@ -2600,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;
@@ -2742,13 +2744,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;
	}

@@ -2813,7 +2815,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);
@@ -3029,13 +3031,13 @@ static int glink_tx_common(void *handle, void *pkt_priv,
		xprt_schedule_tx(ctx->transport_ptr, ctx, tx_info);

	rwref_read_put(&ctx->ch_state_lhb2);
	glink_put_ch_ctx(ctx, false);
	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;
}
@@ -3085,7 +3087,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;
	}

@@ -3094,14 +3096,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;
	}

@@ -3111,7 +3113,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);
@@ -3143,12 +3145,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);
@@ -3177,7 +3179,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;
	}

@@ -3203,7 +3205,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);
@@ -3257,7 +3259,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;
	}

@@ -3267,7 +3269,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);
@@ -3293,12 +3295,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);
@@ -3325,12 +3327,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);
@@ -3434,7 +3436,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;
	}

@@ -3444,7 +3446,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);
@@ -3468,12 +3470,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);
@@ -3500,7 +3502,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;
	}

@@ -3509,7 +3511,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);
@@ -3537,11 +3539,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,
@@ -3549,6 +3551,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);
		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);
	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);
		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);
	return ret;
}

/**
 * glink_rpm_rx_poll() - Poll and receive any available events
 * @handle:	Channel handle in which this operation is performed.
@@ -3631,10 +3688,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);
@@ -3956,6 +4013,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);
@@ -6175,7 +6236,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();
+54 −0
Original line number Diff line number Diff line
@@ -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;
@@ -2124,6 +2128,52 @@ static int power_unvote(struct glink_transport_if *if_ptr)
	return 0;
}

/**
 * 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.
@@ -2169,6 +2219,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;
}

/**
@@ -2341,6 +2393,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]) {
+3 −1
Original line number Diff line number Diff line
/* 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.
+28 −1
Original line number Diff line number Diff line
/* 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
@@ -340,6 +340,22 @@ int glink_qos_start(void *handle);
 */
unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size);

/**
 * 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);

/**
 * 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);

#else /* CONFIG_MSM_GLINK */
static inline void *glink_open(const struct glink_open_config *cfg_ptr)
{
@@ -428,5 +444,16 @@ static inline unsigned long glink_qos_get_ramp_time(void *handle,
{
	return 0;
}

static inline int glink_start_rx_rt(void *handle)
{
	return -ENODEV;
}

static inline int glink_end_rx_rt(void *handle)
{
	return -ENODEV;
}

#endif /* CONFIG_MSM_GLINK */
#endif /* _SOC_QCOM_GLINK_H_ */