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

Commit 01f05a50 authored by Gidon Studinski's avatar Gidon Studinski
Browse files

msm: ipa: enable HOLB on IPA producer pipes for IPA 2.0



On IPA 1.1 suspending a pipe results in immediate packet drop. On IPA 2.0
the behavior has changed and the packets stall IPA, while raising an
interrupt to SW. This change enables Head Of Line Blocking, which results
in the same behavior on IPA 2.0 and IPA 1.1.

Change-Id: I51716c07ed7f81f9031d4c1eb1c7fb9349321cbd
Signed-off-by: default avatarGidon Studinski <gidons@codeaurora.org>
parent a6ab33fa
Loading
Loading
Loading
Loading
+40 −8
Original line number Diff line number Diff line
@@ -17,37 +17,63 @@
 * directional throughputs
 */
#define IPA_A2_HOLB_TMR_EN 0x1
#define IPA_A2_HOLB_TMR_DIS 0x0
#define IPA_A2_HOLB_TMR_DEFAULT_VAL 0x1ff

#define IPA_PKT_FLUSH_TO_US 100

static void ipa_enable_data_path(u32 clnt_hdl)
int ipa_enable_data_path(u32 clnt_hdl)
{
	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
	struct ipa_ep_cfg_holb holb_cfg;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	int res = 0;

	IPADBG("Enabling data path\n");

	/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL)
		return;
		return 0;

	memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl));
	/* On IPA 2.0, disable HOLB */
	if (ipa_ctx->ipa_hw_type == IPA_HW_v2_0 &&
	    IPA_CLIENT_IS_CONS(ep->client)) {
		memset(&holb_cfg, 0 , sizeof(holb_cfg));
		holb_cfg.en = IPA_A2_HOLB_TMR_DIS;
		holb_cfg.tmr_val = 0;
		res = ipa_cfg_ep_holb(clnt_hdl, &holb_cfg);
	}

	/* Enable the pipe */
	memset(&ep_cfg_ctrl, 0 , sizeof(ep_cfg_ctrl));
	ep_cfg_ctrl.ipa_ep_suspend = false;

	ipa_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);

	return res;
}

static int ipa_disable_data_path(u32 clnt_hdl)
int ipa_disable_data_path(u32 clnt_hdl)
{
	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
	struct ipa_ep_cfg_holb holb_cfg;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	int res = 0;

	IPADBG("Disabling data path\n");

	/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL)
		return 0;

	/* On IPA 2.0, enable HOLB in order to prevent IPA from stalling */
	if (ipa_ctx->ipa_hw_type == IPA_HW_v2_0 &&
	    IPA_CLIENT_IS_CONS(ep->client)) {
		memset(&holb_cfg, 0 , sizeof(holb_cfg));
		holb_cfg.en = IPA_A2_HOLB_TMR_EN;
		holb_cfg.tmr_val = 0;
		res = ipa_cfg_ep_holb(clnt_hdl, &holb_cfg);
	}

	/* Suspend the pipe */
	memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl));
	ep_cfg_ctrl.ipa_ep_suspend = true;

@@ -59,7 +85,7 @@ static int ipa_disable_data_path(u32 clnt_hdl)
			ep->cfg.aggr.aggr_time_limit)
		msleep(ep->cfg.aggr.aggr_time_limit);

	return 0;
	return res;
}

static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -212,13 +238,19 @@ int ipa_connect(const struct ipa_connect_params *in, struct ipa_sps_params *sps,

	memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
	ipa_inc_client_enable_clks();
	ipa_enable_data_path(ipa_ep_idx);

	ep->valid = 1;
	ep->client = in->client;
	ep->client_notify = in->notify;
	ep->priv = in->priv;

	result = ipa_enable_data_path(ipa_ep_idx);
	if (result) {
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
				ipa_ep_idx);
		goto ipa_cfg_ep_fail;
	}

	if (ipa_ctx->ipa_hw_type != IPA_HW_v2_0 || ep->priv == NULL ||
	    (enum ipa_config_this_ep)ep->priv != IPA_DO_NOT_CONFIGURE_THIS_EP) {
		if (ipa_cfg_ep(ipa_ep_idx, &in->ipa_ep_cfg)) {
+9 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, 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
@@ -963,6 +963,13 @@ int ipa_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)

	spin_lock_init(&ep->sys->spinlock);

	result = ipa_enable_data_path(ipa_ep_idx);
	if (result) {
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
				ipa_ep_idx);
		goto fail_gen2;
	}

	if (ipa_cfg_ep(ipa_ep_idx, &sys_in->ipa_ep_cfg)) {
		IPAERR("fail to configure EP.\n");
		goto fail_gen2;
@@ -1088,6 +1095,7 @@ int ipa_teardown_sys_pipe(u32 clnt_hdl)
	if (IPA_CLIENT_IS_CONS(ep->client))
		ipa_cleanup_rx(ep->sys);

	ipa_disable_data_path(clnt_hdl);
	sps_disconnect(ep->ep_hdl);
	dma_free_coherent(NULL, ep->connect.desc.size,
			  ep->connect.desc.base,
+3 −0
Original line number Diff line number Diff line
@@ -967,4 +967,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip,

void ipa_skb_recycle(struct sk_buff *skb);

int ipa_enable_data_path(u32 clnt_hdl);
int ipa_disable_data_path(u32 clnt_hdl);

#endif /* _IPA_I_H_ */