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

Commit 28e5f7af authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa3: Software workaround to fix GSI2.2 HW bug in SM6150"

parents dcb40bc8 b188a2d9
Loading
Loading
Loading
Loading
+124 −44
Original line number Diff line number Diff line
@@ -2151,6 +2151,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
	atomic_set(&ctx->poll_mode, GSI_CHAN_MODE_CALLBACK);
	ctx->props = *props;

	if (gsi_ctx->per.ver != GSI_VER_2_2) {
		mutex_lock(&gsi_ctx->mlock);
		ee = gsi_ctx->per.ee;
		gsi_ctx->ch_dbg[props->ch_id].ch_allocate++;
@@ -2175,7 +2176,11 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
			return -GSI_STATUS_RES_ALLOC_FAILURE;
		}
		mutex_unlock(&gsi_ctx->mlock);

	} else {
		mutex_lock(&gsi_ctx->mlock);
		ctx->state = GSI_CHAN_STATE_ALLOCATED;
		mutex_unlock(&gsi_ctx->mlock);
	}
	erindex = props->evt_ring_hdl != ~0 ? props->evt_ring_hdl :
		GSI_NO_EVT_ERINDEX;
	if (erindex != GSI_NO_EVT_ERINDEX) {
@@ -2748,6 +2753,8 @@ int gsi_dealloc_channel(unsigned long chan_hdl)
		return -GSI_STATUS_UNSUPPORTED_OP;
	}

	/*In GSI_VER_2_2 version deallocation channel not supported*/
	if (gsi_ctx->per.ver != GSI_VER_2_2) {
		mutex_lock(&gsi_ctx->mlock);
		reinit_completion(&ctx->compl);

@@ -2772,7 +2779,14 @@ int gsi_dealloc_channel(unsigned long chan_hdl)
		}

		mutex_unlock(&gsi_ctx->mlock);

	} else {
		mutex_lock(&gsi_ctx->mlock);
		GSIDBG("In GSI_VER_2_2 channel deallocation not supported\n");
		ctx->state = GSI_CHAN_STATE_NOT_ALLOCATED;
		GSIDBG("chan_hdl=%lu Channel state = %u\n", chan_hdl,
								ctx->state);
		mutex_unlock(&gsi_ctx->mlock);
	}
	devm_kfree(gsi_ctx->dev, ctx->user_data);
	ctx->allocated = false;
	if (ctx->evtr)
@@ -3582,6 +3596,72 @@ int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code)
}
EXPORT_SYMBOL(gsi_halt_channel_ee);

int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code)
{
	enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_ALLOC_CHANNEL;
	struct gsi_chan_ctx *ctx;
	uint32_t val;
	int res;

	if (chan_idx >= gsi_ctx->max_ch || !code) {
		GSIERR("bad params chan_idx=%d\n", chan_idx);
		return -GSI_STATUS_INVALID_PARAMS;
	}

	mutex_lock(&gsi_ctx->mlock);
	reinit_completion(&gsi_ctx->gen_ee_cmd_compl);

	/* invalidate the response */
	gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
			GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
	gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0;
	gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base +
			GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));

	val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) &
		GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) |
		((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) &
			GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) |
		((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) &
			GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK));
	gsi_writel(val, gsi_ctx->base +
		GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee));

	res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl,
		msecs_to_jiffies(GSI_CMD_TIMEOUT));
	if (res == 0) {
		GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee);
		res = -GSI_STATUS_TIMED_OUT;
		goto free_lock;
	}

	gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
		GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
	if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
		GSI_GEN_EE_CMD_RETURN_CODE_OUT_OF_RESOURCES) {
		GSIDBG("chan_idx=%u ee=%u out of resources\n", chan_idx, ee);
		*code = GSI_GEN_EE_CMD_RETURN_CODE_OUT_OF_RESOURCES;
		res = -GSI_STATUS_RES_ALLOC_FAILURE;
		goto free_lock;
	}
	if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) {
		GSIERR("No response received\n");
		res = -GSI_STATUS_ERROR;
		goto free_lock;
	}
	if (ee == 0) {
		ctx = &gsi_ctx->chan[chan_idx];
		gsi_ctx->ch_dbg[chan_idx].ch_allocate++;
	}
	res = GSI_STATUS_SUCCESS;
	*code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code;
free_lock:
	mutex_unlock(&gsi_ctx->mlock);

	return res;
}
EXPORT_SYMBOL(gsi_alloc_channel_ee);

int gsi_map_virtual_ch_to_per_ep(u32 ee, u32 chan_num, u32 per_ep_index)
{
	if (!gsi_ctx) {
+2 −0
Original line number Diff line number Diff line
@@ -295,6 +295,7 @@ enum gsi_evt_ch_cmd_opcode {

enum gsi_generic_ee_cmd_opcode {
	GSI_GEN_EE_CMD_HALT_CHANNEL = 0x1,
	GSI_GEN_EE_CMD_ALLOC_CHANNEL = 0x2,
};

enum gsi_generic_ee_cmd_return_code {
@@ -304,6 +305,7 @@ enum gsi_generic_ee_cmd_return_code {
	GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE = 0x4,
	GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX = 0x5,
	GSI_GEN_EE_CMD_RETURN_CODE_RETRY = 0x6,
	GSI_GEN_EE_CMD_RETURN_CODE_OUT_OF_RESOURCES = 0x7,
};

extern struct gsi_ctx *gsi_ctx;
+44 −0
Original line number Diff line number Diff line
@@ -4444,6 +4444,38 @@ static int ipa3_gsi_pre_fw_load_init(void)
	return 0;
}

static int ipa3_alloc_gsi_channel(void)
{
	const struct ipa_gsi_ep_config *gsi_ep_cfg;
	enum ipa_client_type type;
	int code = 0;
	int ret = 0;
	int i;

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		type = ipa3_get_client_by_pipe(i);
		gsi_ep_cfg = ipa3_get_gsi_ep_info(type);
		IPADBG("for ep %d client is %d\n", i, type);
		if (!gsi_ep_cfg)
			continue;

		ret = gsi_alloc_channel_ee(gsi_ep_cfg->ipa_gsi_chan_num,
					gsi_ep_cfg->ee, &code);
		if (ret == GSI_STATUS_SUCCESS) {
			IPADBG("alloc gsi ch %d ee %d with code %d\n",
					gsi_ep_cfg->ipa_gsi_chan_num,
					gsi_ep_cfg->ee,
					code);
		} else {
			IPAERR("failed to alloc ch %d ee %d code %d\n",
					gsi_ep_cfg->ipa_gsi_chan_num,
					gsi_ep_cfg->ee,
					code);
			return ret;
		}
	}
	return ret;
}
/**
 * ipa3_post_init() - Initialize the IPA Driver (Part II).
 * This part contains all initialization which requires interaction with
@@ -4671,6 +4703,17 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_register_device;
	}
	IPADBG("IPA gsi is registered\n");
	/* GSI 2.2 requires to allocate all EE GSI channel
	 * during device bootup.
	 */
	if (ipa3_get_gsi_ver(resource_p->ipa_hw_type) == GSI_VER_2_2) {
		result = ipa3_alloc_gsi_channel();
		if (result) {
			IPAERR("Failed to alloc the GSI channels\n");
			result = -ENODEV;
			goto fail_alloc_gsi_channel;
		}
	}

	/* setup the AP-IPA pipes */
	if (ipa3_setup_apps_pipes()) {
@@ -4734,6 +4777,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,

fail_teth_bridge_driver_init:
	ipa3_teardown_apps_pipes();
fail_alloc_gsi_channel:
fail_setup_apps_pipes:
	gsi_deregister_device(ipa3_ctx->gsi_dev_hdl, false);
fail_register_device:
+1 −0
Original line number Diff line number Diff line
@@ -2325,6 +2325,7 @@ void ipa3_proxy_clk_unvote(void);
bool ipa3_is_client_handle_valid(u32 clnt_hdl);

enum ipa_client_type ipa3_get_client_mapping(int pipe_idx);
enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx);

void ipa_init_ep_flt_bitmap(void);

+1 −1
Original line number Diff line number Diff line
@@ -3607,7 +3607,7 @@ enum ipa_client_type ipa3_get_client_mapping(int pipe_idx)
 *
 * Return value: client type
 */
static enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx)
enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx)
{
	int j = 0;

Loading