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

Commit 26f280d9 authored by Ravi Gummadidala's avatar Ravi Gummadidala Committed by Gerrit - the friendly Code Review server
Browse files

msm: gsi: add new API to check (GPI) channel emptiness



This is needed by clients to determine idleness of a channel
before operations like disconnect, going to low power mode, etc.

Change-Id: I6d84e92d20a0a977e578ac366f1b1aaf4d2937b9
Signed-off-by: default avatarRavi Gummadidala <rgummadi@codeaurora.org>
parent 718b9859
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
@@ -1736,7 +1736,7 @@ int gsi_stop_channel(unsigned long chan_hdl)
	res = wait_for_completion_timeout(&ctx->compl,
			msecs_to_jiffies(GSI_STOP_CMD_TIMEOUT_MS));
	if (res == 0) {
		GSIERR("chan_hdl=%lu timed out\n", chan_hdl);
		GSIDBG("chan_hdl=%lu timed out\n", chan_hdl);
		res = -GSI_STATUS_TIMED_OUT;
		goto free_lock;
	}
@@ -2056,6 +2056,66 @@ int gsi_query_channel_info(unsigned long chan_hdl,
}
EXPORT_SYMBOL(gsi_query_channel_info);

int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty)
{
	struct gsi_chan_ctx *ctx;
	spinlock_t *slock;
	unsigned long flags;
	uint64_t rp;
	uint64_t wp;
	int ee = gsi_ctx->per.ee;

	if (!gsi_ctx) {
		pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
		return -GSI_STATUS_NODEV;
	}

	if (chan_hdl >= GSI_MAX_CHAN || !is_empty) {
		GSIERR("bad params chan_hdl=%lu is_empty=%p\n",
				chan_hdl, is_empty);
		return -GSI_STATUS_INVALID_PARAMS;
	}

	ctx = &gsi_ctx->chan[chan_hdl];

	if (ctx->props.prot != GSI_CHAN_PROT_GPI) {
		GSIERR("op not supported for protocol %u\n", ctx->props.prot);
		return -GSI_STATUS_UNSUPPORTED_OP;
	}

	if (ctx->evtr)
		slock = &ctx->evtr->ring.slock;
	else
		slock = &ctx->ring.slock;

	spin_lock_irqsave(slock, flags);

	rp = gsi_readl(gsi_ctx->base +
		GSI_EE_n_GSI_CH_k_CNTXT_4_OFFS(ctx->props.ch_id, ee));
	rp |= ((uint64_t)gsi_readl(gsi_ctx->base +
		GSI_EE_n_GSI_CH_k_CNTXT_5_OFFS(ctx->props.ch_id, ee))) << 32;
	ctx->ring.rp = rp;

	wp = gsi_readl(gsi_ctx->base +
		GSI_EE_n_GSI_CH_k_CNTXT_6_OFFS(ctx->props.ch_id, ee));
	wp |= ((uint64_t)gsi_readl(gsi_ctx->base +
		GSI_EE_n_GSI_CH_k_CNTXT_7_OFFS(ctx->props.ch_id, ee))) << 32;
	ctx->ring.wp = wp;

	if (ctx->props.dir == GSI_CHAN_DIR_FROM_GSI)
		*is_empty = (ctx->ring.rp_local == rp) ? true : false;
	else
		*is_empty = (wp == rp) ? true : false;

	spin_unlock_irqrestore(slock, flags);

	GSIDBG("ch=%lu RP=0x%llx WP=0x%llx RP_LOCAL=0x%llx\n",
			chan_hdl, rp, wp, ctx->ring.rp_local);

	return GSI_STATUS_SUCCESS;
}
EXPORT_SYMBOL(gsi_is_channel_empty);

int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers,
		struct gsi_xfer_elem *xfer, bool ring_db)
{
+18 −0
Original line number Diff line number Diff line
@@ -861,6 +861,19 @@ int gsi_query_channel_db_addr(unsigned long chan_hdl,
int gsi_query_channel_info(unsigned long chan_hdl,
		struct gsi_chan_info *info);

/**
 * gsi_is_channel_empty - Peripheral can call this function to query if
 * the channel is empty. This is only applicable to GPI. "Empty" means
 * GSI has consumed all descriptors for a TO_GSI channel and SW has
 * processed all completed descriptors for a FROM_GSI channel.
 *
 * @chan_hdl:  Client handle previously obtained from gsi_alloc_channel
 * @is_empty:  set by GSI based on channel emptiness
 *
 * @Return gsi_status
 */
int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty);

/**
 * gsi_get_channel_cfg - This function returns the current config
 * of the specified channel
@@ -1073,6 +1086,11 @@ static inline int gsi_query_channel_info(unsigned long chan_hdl,
	return -GSI_STATUS_UNSUPPORTED_OP;
}

static inline int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty)
{
	return -GSI_STATUS_UNSUPPORTED_OP;
}

static inline int gsi_poll_channel(unsigned long chan_hdl,
		struct gsi_chan_xfer_notify *notify)
{