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

Commit 20faea80 authored by Mohammed Javid's avatar Mohammed Javid Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa4: Increase the GSI command poll timeout to 10



In some scenarios IPA apps not receiving the GSI interrupt even
GSI register bit set after sending commands. Added changes to assert
the device if interrupt was not received after some retries,
instead of waiting for continuously in loop.

Change-Id: I12ecc402c3d3399efb43f2f1351a364222b0d13f
Acked-by: default avatarPraveen Kurapati <pkurapat@codeaurora.org>
Acked-by: default avatarBojun Pan <bojunp@codeaurora.org>
Acked-by: default avatarAshok Vuyyuru <avuyyuru@qti.qualcomm.com>
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent 3b3e314b
Loading
Loading
Loading
Loading
+71 −18
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#define GSI_STOP_CMD_TIMEOUT_MS 200
#define GSI_MAX_CH_LOW_WEIGHT 15

#define GSI_STOP_CMD_POLL_CNT 4
#define GSI_STOP_IN_PROC_CMD_POLL_CNT 2

#define GSI_RESET_WA_MIN_SLEEP 1000
#define GSI_RESET_WA_MAX_SLEEP 2000
#define GSI_CHNL_STATE_MAX_RETRYCNT 10
@@ -111,17 +114,21 @@ static void __gsi_config_gen_irq(int ee, uint32_t mask, uint32_t val)

static void gsi_channel_state_change_wait(unsigned long chan_hdl,
	struct gsi_chan_ctx *ctx,
	uint32_t tm)
	uint32_t tm, enum gsi_ch_cmd_opcode op)
{
	int poll_cnt;
	int gsi_pending_intr;
	int res;
	uint32_t ch;
	uint32_t type;
	uint32_t val;
	int ee = gsi_ctx->per.ee;
	enum gsi_chan_state curr_state = GSI_CHAN_STATE_NOT_ALLOCATED;
	int stop_in_proc_retry = 0;
	int stop_retry = 0;

	/*
	 * Start polling the GSI channel for
	 * duration = tm * poll_cnt.
	 * duration = tm * GSI_CMD_POLL_CNT.
	 * We need to do polling of gsi state for improving debugability
	 * of gsi hw state.
	 */
@@ -136,28 +143,71 @@ static void gsi_channel_state_change_wait(unsigned long chan_hdl,
		if (res != 0)
			return;

		/*
		 * for the case of pending interrupt we will continue in the
		 * loop. So state update is not needed.
		 */

		ch = gsi_readl(gsi_ctx->base +
		type = gsi_readl(gsi_ctx->base +
			GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(gsi_ctx->per.ee));

		gsi_pending_intr = gsi_readl(gsi_ctx->base +
			GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_OFFS(ee));

		/* Update the channel state only if interrupt was raised
		 * on praticular channel and also checking global interrupt
		 * is raised for channel control.
		 */
		if ((type & GSI_EE_n_CNTXT_TYPE_IRQ_CH_CTRL_BMSK) &&
				((gsi_pending_intr >> chan_hdl) & 1)) {
			/*
		 * Continue in the loop if a pending interrupt of
		 * corresponding channel is present till an interrupt
		 * is received.
			 * Check channel state here in case the channel is
			 * already started but interrupt is not yet received.
			 */
			val = gsi_readl(gsi_ctx->base +
				GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl,
					gsi_ctx->per.ee));
			curr_state = (val &
				GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >>
				GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT;
		}

		if (op == GSI_CH_START) {
			if (curr_state == GSI_CHAN_STATE_STARTED) {
				ctx->state = curr_state;
				return;
			}
		}

		if (op == GSI_CH_STOP) {
			if (curr_state == GSI_CHAN_STATE_STOPPED)
				stop_retry++;
			else if (curr_state == GSI_CHAN_STATE_STOP_IN_PROC)
				stop_in_proc_retry++;
		}

		/* if interrupt marked reg after poll count reaching to max
		 * keep loop to continue reach max stop proc and max stop count.
		 */
		if ((gsi_pending_intr >> chan_hdl) & 1)
		if (stop_retry == 1 || stop_in_proc_retry == 1)
			poll_cnt = 0;

		GSIDBG("GSI wait on chan_hld=%lu chan=%lu state=%u intr=%u\n",
		/* If stop channel retry reached to max count
		 * clear the pending interrupt, if channel already stopped.
		 */
		if (stop_retry == GSI_STOP_CMD_POLL_CNT) {
			gsi_writel(gsi_pending_intr, gsi_ctx->base +
				GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_OFFS(ee));
			ctx->state = curr_state;
			return;
		}

		/* If channel state stop in progress case no need
		 * to wait for long time.
		 */
		if (stop_in_proc_retry == GSI_STOP_IN_PROC_CMD_POLL_CNT) {
			ctx->state = curr_state;
			return;
		}

		GSIDBG("GSI wait on chan_hld=%lu irqtyp=%lu state=%u intr=%u\n",
			chan_hdl,
			ch,
			type,
			ctx->state,
			gsi_pending_intr);
	}
@@ -746,6 +796,8 @@ static irqreturn_t gsi_isr(int irq, void *ctxt)
			gsi_handle_irq();
			gsi_ctx->per.rel_clk_cb(gsi_ctx->per.user_data);
		}
	} else if (!gsi_ctx->per.clk_status_cb()) {
		return IRQ_HANDLED;
	} else {
		gsi_handle_irq();
	}
@@ -2699,7 +2751,7 @@ int gsi_start_channel(unsigned long chan_hdl)
	GSIDBG("GSI Channel Start, waiting for completion\n");
	gsi_channel_state_change_wait(chan_hdl,
		ctx,
		GSI_START_CMD_TIMEOUT_MS);
		GSI_START_CMD_TIMEOUT_MS, op);

	if (ctx->state != GSI_CHAN_STATE_STARTED) {
		/*
@@ -2781,12 +2833,13 @@ int gsi_stop_channel(unsigned long chan_hdl)
	GSIDBG("GSI Channel Stop, waiting for completion\n");
	gsi_channel_state_change_wait(chan_hdl,
		ctx,
		GSI_STOP_CMD_TIMEOUT_MS);
		GSI_STOP_CMD_TIMEOUT_MS, op);

	if (ctx->state != GSI_CHAN_STATE_STOPPED &&
		ctx->state != GSI_CHAN_STATE_STOP_IN_PROC) {
		GSIERR("chan=%lu unexpected state=%u\n", chan_hdl, ctx->state);
		res = -GSI_STATUS_BAD_STATE;
		BUG();
		goto free_lock;
	}

+12 −1
Original line number Diff line number Diff line
@@ -3600,7 +3600,7 @@ void ipa3_enable_clks(void)
	if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
	    ipa3_get_bus_vote()))
		WARN(1, "bus scaling failed");

	atomic_set(&ipa3_ctx->ipa_clk_vote, 1);
	ipa3_ctx->ctrl->ipa3_enable_clks();
}

@@ -3636,6 +3636,7 @@ void ipa3_disable_clks(void)

	if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl, 0))
		WARN(1, "bus scaling failed");
	atomic_set(&ipa3_ctx->ipa_clk_vote, 0);
}

/**
@@ -3799,6 +3800,15 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
}

/**
 * ipa3_active_clks_status() - update the current msm bus clock vote
 * status
 */
int ipa3_active_clks_status(void)
{
	return atomic_read(&ipa3_ctx->ipa_clk_vote);
}

/**
 * ipa3_inc_client_enable_clks_no_block() - Only increment the number of active
 * clients if no asynchronous actions should be done. Asynchronous actions are
@@ -4709,6 +4719,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
	gsi_props.notify_cb = ipa_gsi_notify_cb;
	gsi_props.req_clk_cb = NULL;
	gsi_props.rel_clk_cb = NULL;
	gsi_props.clk_status_cb = ipa3_active_clks_status;

	if (ipa3_ctx->ipa_config_is_mhi) {
		gsi_props.mhi_er_id_limits_valid = true;
+1 −0
Original line number Diff line number Diff line
@@ -1648,6 +1648,7 @@ struct ipa3_context {
	struct ipa3_wdi2_ctx wdi2_ctx;
	struct mbox_client mbox_client;
	struct mbox_chan *mbox;
	atomic_t ipa_clk_vote;
};

struct ipa3_plat_drv_res {
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ enum gsi_intr_type {
 *		peripheral is clocked at all times
 * @rel_clk_cb: callback to release peripheral clock
 * @user_data:  cookie used for notifications
 * @clk_status_cb: callback to update the current msm bus clock vote
 *
 * All the callbacks are in interrupt context
 *
@@ -117,6 +118,7 @@ struct gsi_per_props {
	void (*req_clk_cb)(void *user_data, bool *granted);
	int (*rel_clk_cb)(void *user_data);
	void *user_data;
	int (*clk_status_cb)(void);
};

enum gsi_evt_err {