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

Commit cc4bc43f authored by Ashok Vuyyuru's avatar Ashok Vuyyuru Committed by Praveen Kurapati
Browse files

msm: ipa4: support coalescing pipe suspend



Add changes to support coalescing pipe suspend.

Change-Id: I403db535b88da917d43ac52f26ea3fff9b617be5
Signed-off-by: default avatarPraveen Kurapati <pkurapat@codeaurora.org>
Signed-off-by: default avatarAshok Vuyyuru <avuyyuru@codeaurora.org>
Signed-off-by: default avatarMichael Adisumarta <madisuma@codeaurora.org>
parent dc1050aa
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -3703,7 +3703,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
		curr = GSI_CHAN_MODE_CALLBACK;

	if (mode == curr) {
		GSIERR("already in requested mode %u chan_hdl=%lu\n",
		GSIDBG("already in requested mode %u chan_hdl=%lu\n",
				curr, chan_hdl);
		return -GSI_STATUS_UNSUPPORTED_OP;
	}
@@ -3714,7 +3714,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
		gsi_writel(1 << ctx->evtr->id, gsi_ctx->base +
			GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_OFFS(gsi_ctx->per.ee));
		atomic_set(&ctx->poll_mode, mode);
		if (ctx->props.prot == GSI_CHAN_PROT_GCI)
		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan)
			atomic_set(&ctx->evtr->chan->poll_mode, mode);
		GSIDBG("set gsi_ctx evtr_id %d to %d mode\n",
			ctx->evtr->id, mode);
@@ -3724,7 +3724,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
	if (curr == GSI_CHAN_MODE_POLL &&
			mode == GSI_CHAN_MODE_CALLBACK) {
		atomic_set(&ctx->poll_mode, mode);
		if (ctx->props.prot == GSI_CHAN_PROT_GCI)
		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan)
			atomic_set(&ctx->evtr->chan->poll_mode, mode);
		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
		GSIDBG("set gsi_ctx evtr_id %d to %d mode\n",
+1 −0
Original line number Diff line number Diff line
@@ -3008,6 +3008,7 @@ int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple);
int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple);
void ipa3_set_resorce_groups_min_max_limits(void);
int ipa3_suspend_apps_pipes(bool suspend);
void ipa3_force_close_coal(void);
int ipa3_flt_read_tbl_from_hw(u32 pipe_idx,
	enum ipa_ip_type ip_type,
	bool hashable,
+97 −8
Original line number Diff line number Diff line
@@ -7802,7 +7802,7 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl)
	return res;
}

static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend)
static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend)
{
	int ipa_ep_idx;
	struct ipa3_ep_context *ep;
@@ -7829,7 +7829,8 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend)
	 * This needs to happen before starting the channel to make
	 * sure we don't loose any interrupt
	 */
	if (!suspend && !atomic_read(&ep->sys->curr_polling_state))
	if (!suspend && !atomic_read(&ep->sys->curr_polling_state) &&
		!IPA_CLIENT_IS_APPS_PROD(client))
		gsi_config_channel_mode(ep->gsi_chan_hdl,
					GSI_CHAN_MODE_CALLBACK);

@@ -7847,6 +7848,10 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend)
		}
	}

	/* Apps prod pipes use common event ring so cannot configure mode*/
	if (IPA_CLIENT_IS_APPS_PROD(client))
		return 0;

	if (suspend) {
		IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl);
		gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL);
@@ -7861,19 +7866,103 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend)
	return 0;
}

void ipa3_force_close_coal(void)
{
	struct ipahal_imm_cmd_pyld *cmd_pyld = NULL;
	struct ipahal_imm_cmd_register_write reg_write_cmd = { 0 };
	struct ipahal_reg_valmask valmask;
	struct ipa3_desc desc;
	int ep_idx;

	ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
	if (ep_idx == IPA_EP_NOT_ALLOCATED || (!ipa3_ctx->ep[ep_idx].valid))
		return;

	reg_write_cmd.skip_pipeline_clear = false;
	reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
	reg_write_cmd.offset = ipahal_get_reg_ofst(IPA_AGGR_FORCE_CLOSE);
	ipahal_get_aggr_force_close_valmask(ep_idx, &valmask);
	reg_write_cmd.value = valmask.val;
	reg_write_cmd.value_mask = valmask.mask;
	cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
		&reg_write_cmd, false);
	if (!cmd_pyld) {
		IPAERR("fail construct register_write imm cmd\n");
		ipa_assert();
		return;
	}
	ipa3_init_imm_cmd_desc(&desc, cmd_pyld);

	IPADBG("Sending 1 descriptor for coal force close\n");
	if (ipa3_send_cmd_timeout(1, &desc,
		IPA_DMA_TASK_FOR_GSI_TIMEOUT_MSEC)) {
		IPAERR("ipa3_send_cmd failed\n");
		ipa_assert();
	}
	ipahal_destroy_imm_cmd(cmd_pyld);
}

int ipa3_suspend_apps_pipes(bool suspend)
{
	int res;
	enum ipa_client_type client;

	res = _ipa_suspend_pipe(IPA_CLIENT_APPS_LAN_CONS, suspend);
	if (suspend)
		ipa3_force_close_coal();

	for (client = 0; client < IPA_CLIENT_MAX; client++) {
		if (IPA_CLIENT_IS_APPS_CONS(client)) {
			res = _ipa_suspend_resume_pipe(client, suspend);
			if (res)
		return res;
				goto undo_cons;
		}
	}

	if (suspend) {
		struct ipahal_reg_tx_wrapper tx;
		int ep_idx;

		ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
		if (ep_idx == IPA_EP_NOT_ALLOCATED ||
				(!ipa3_ctx->ep[ep_idx].valid))
			goto do_prod;

	res = _ipa_suspend_pipe(IPA_CLIENT_APPS_WAN_CONS, suspend);
		ipahal_read_reg_fields(IPA_STATE_TX_WRAPPER, &tx);
		if (tx.coal_slave_open_frame != 0) {
			IPADBG("COAL frame is open 0x%x\n",
				tx.coal_slave_open_frame);
			goto undo_cons;
		}

		usleep_range(IPA_TAG_SLEEP_MIN_USEC, IPA_TAG_SLEEP_MAX_USEC);

		res = ipahal_read_reg_n(IPA_SUSPEND_IRQ_INFO_EE_n,
			ipa3_ctx->ee);
		if (res) {
			IPADBG("suspend irq is pending 0x%x\n", res);
			goto undo_cons;
		}
	}
do_prod:
	for (client = 0; client < IPA_CLIENT_MAX; client++) {
		if (IPA_CLIENT_IS_APPS_PROD(client)) {
			res = _ipa_suspend_resume_pipe(client, suspend);
			if (res)
		return res;
				goto undo_prod;
		}
	}

	return 0;
undo_prod:
	for (client--; client < IPA_CLIENT_MAX && client >= 0; client--)
		if (IPA_CLIENT_IS_APPS_PROD(client))
			_ipa_suspend_resume_pipe(client, !suspend);
	client = IPA_CLIENT_MAX;
undo_cons:
	for (client--; client < IPA_CLIENT_MAX && client >= 0; client--)
		if (IPA_CLIENT_IS_APPS_CONS(client))
			_ipa_suspend_resume_pipe(client, !suspend);
	return res;
}

int ipa3_allocate_dma_task_for_gsi(void)
+70 −0
Original line number Diff line number Diff line
@@ -1187,6 +1187,73 @@ static void ipareg_parse_comp_cfg_v4_5(
		IPA_COMP_CFG_IPA_FULL_FLUSH_WAIT_RSC_CLOSURE_EN_BMSK_v4_5);
}

static void ipareg_parse_state_tx_wrapper_v4_5(
	enum ipahal_reg_name reg, void *fields, u32 val)
{
	struct ipahal_reg_tx_wrapper *tx =
		(struct ipahal_reg_tx_wrapper *)fields;

	tx->tx0_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_TX0_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_TX0_IDLE_BMSK);

	tx->tx1_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_TX1_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_TX1_IDLE_BMSK);

	tx->ipa_prod_ackmngr_db_empty = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_SHFT,
		IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_BMSK);

	tx->ipa_prod_ackmngr_state_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_BMSK);

	tx->ipa_prod_prod_bresp_empty = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT,
		IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK);

	tx->ipa_prod_prod_bresp_toggle_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT,
		IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK);

	tx->ipa_mbim_pkt_fms_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_BMSK);

	tx->mbim_direct_dma = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_SHFT,
		IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_BMSK);

	tx->trnseq_force_valid = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_SHFT,
		IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_BMSK);

	tx->pkt_drop_cnt_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_BMSK);

	tx->nlo_direct_dma = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_SHFT,
		IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_BMSK);

	tx->coal_direct_dma = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_SHFT,
		IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_BMSK);

	tx->coal_slave_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_BMSK);

	tx->coal_slave_ctx_idle = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_SHFT,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_BMSK);

	tx->coal_slave_open_frame = IPA_GETFIELD_FROM_REG(val,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_SHFT,
		IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_BMSK);
}

static void ipareg_construct_qcncm(
	enum ipahal_reg_name reg, const void *fields, u32 *val)
{
@@ -2975,6 +3042,9 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
	[IPA_HW_v4_5][IPA_COMP_CFG] = {
		ipareg_construct_comp_cfg_v4_5, ipareg_parse_comp_cfg_v4_5,
		0x0000003C, 0, 0, 0, 0},
	[IPA_HW_v4_5][IPA_STATE_TX_WRAPPER] = {
		ipareg_construct_dummy, ipareg_parse_state_tx_wrapper_v4_5,
		0x00000090, 0, 0, 0, 1 },
	[IPA_HW_v4_5][IPA_STATE_FETCHER_MASK] = {
		ipareg_construct_dummy, ipareg_parse_dummy,
		-1, 0, 0, 0, 0},
+22 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, 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
@@ -386,6 +386,27 @@ struct ipahal_reg_comp_cfg {
	bool enable;
};

/*
 * struct ipahal_reg_tx_wrapper- IPA TX Wrapper state information
 */
struct ipahal_reg_tx_wrapper {
	bool tx0_idle;
	bool tx1_idle;
	bool ipa_prod_ackmngr_db_empty;
	bool ipa_prod_ackmngr_state_idle;
	bool ipa_prod_prod_bresp_empty;
	bool ipa_prod_prod_bresp_toggle_idle;
	bool ipa_mbim_pkt_fms_idle;
	u8 mbim_direct_dma;
	bool trnseq_force_valid;
	bool pkt_drop_cnt_idle;
	u8 nlo_direct_dma;
	u8 coal_direct_dma;
	bool coal_slave_idle;
	bool coal_slave_ctx_idle;
	u8 coal_slave_open_frame;
};

/*
 * struct ipa_hash_tuple - Hash tuple members for flt and rt
 *  the fields tells if to be masked or not
Loading