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

Commit a699afd8 authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: ipa4: remove IPA_ENDP_INIT_CTRL_n.ENDP_SUSPEND usage



On IPA 4.0 HW there is no support for pipe suspend.
Instead corresponding GSI channel needs to be stopped.

Change-Id: I6cf3e6a5a52a88ddb3a2ab2380c741163ac555a1
CRs-Fixed: 2054613
Acked-by: default avatarAdy Abraham <adya@qti.qualcomm.com>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent df5f2340
Loading
Loading
Loading
Loading
+5 −60
Original line number Diff line number Diff line
@@ -495,63 +495,6 @@ static int ipa3_open(struct inode *inode, struct file *filp)
	return 0;
}

/**
* ipa3_flow_control() - Enable/Disable flow control on a particular client.
* Return codes:
* None
*/
void ipa3_flow_control(enum ipa_client_type ipa_client,
		bool enable, uint32_t qmap_id)
{
	struct ipa_ep_cfg_ctrl ep_ctrl = {0};
	int ep_idx;
	struct ipa3_ep_context *ep;

	/* Check if tethered flow control is needed or not.*/
	if (!ipa3_ctx->tethered_flow_control) {
		IPADBG("Apps flow control is not needed\n");
		return;
	}

	/* Check if ep is valid. */
	ep_idx = ipa3_get_ep_mapping(ipa_client);
	if (ep_idx == -1) {
		IPADBG("Invalid IPA client\n");
		return;
	}

	ep = &ipa3_ctx->ep[ep_idx];
	if (!ep->valid || (ep->client != IPA_CLIENT_USB_PROD)) {
		IPADBG("EP not valid/Not applicable for client.\n");
		return;
	}

	spin_lock(&ipa3_ctx->disconnect_lock);
	/* Check if the QMAP_ID matches. */
	if (ep->cfg.meta.qmap_id != qmap_id) {
		IPADBG("Flow control ind not for same flow: %u %u\n",
			ep->cfg.meta.qmap_id, qmap_id);
		spin_unlock(&ipa3_ctx->disconnect_lock);
		return;
	}
	if (!ep->disconnect_in_progress) {
		if (enable) {
			IPADBG("Enabling Flow\n");
			ep_ctrl.ipa_ep_delay = false;
			IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_enable);
		} else {
			IPADBG("Disabling Flow\n");
			ep_ctrl.ipa_ep_delay = true;
			IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_disable);
		}
		ep_ctrl.ipa_ep_suspend = false;
		ipa3_cfg_ep_ctrl(ep_idx, &ep_ctrl);
	} else {
		IPADBG("EP disconnect is in progress\n");
	}
	spin_unlock(&ipa3_ctx->disconnect_lock);
}

static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type)
{
	if (!buff) {
@@ -1863,6 +1806,8 @@ static void ipa3_q6_avoid_holb(void)
				IPA_ENDP_INIT_HOL_BLOCK_EN_n,
				ep_idx, &ep_holb);

			/* from IPA 4.0 pipe suspend is not supported */
			if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
				ipahal_write_reg_n_fields(
					IPA_ENDP_INIT_CTRL_n,
					ep_idx, &ep_suspend);
+60 −44
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ int ipa3_enable_data_path(u32 clnt_hdl)
	}

	/* Enable the pipe */
	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		if (IPA_CLIENT_IS_CONS(ep->client) &&
		    (ep->keep_ipa_awake ||
		    ipa3_ctx->resume_on_connect[ep->client] ||
@@ -77,6 +78,7 @@ int ipa3_enable_data_path(u32 clnt_hdl)
			ep_cfg_ctrl.ipa_ep_suspend = false;
			res = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
		}
	}

	return res;
}
@@ -97,18 +99,24 @@ int ipa3_disable_data_path(u32 clnt_hdl)
		res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg);
	}

	/*
	 * for IPA 4.0 and above aggregation frame is closed together with
	 * channel STOP
	 */
	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		/* Suspend the pipe */
		if (IPA_CLIENT_IS_CONS(ep->client)) {
			/*
		 * for RG10 workaround uC needs to be loaded before pipe can
		 * be suspended in this case.
			 * for RG10 workaround uC needs to be loaded before
			 * pipe can be suspended in this case.
			 */
			if (ipa3_ctx->apply_rg10_wa && ipa3_uc_state_check()) {
				IPADBG("uC is not loaded yet, waiting...\n");
				res = wait_for_completion_timeout(
				&ipa3_ctx->uc_loaded_completion_obj, 60 * HZ);
					&ipa3_ctx->uc_loaded_completion_obj,
					60 * HZ);
				if (res == 0)
				IPADBG("timeout waiting for uC to load\n");
					IPADBG("timeout waiting for uC load\n");
			}

			memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
@@ -117,13 +125,15 @@ int ipa3_disable_data_path(u32 clnt_hdl)
		}

		udelay(IPA_PKT_FLUSH_TO_US);
	ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr);
		ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl,
			&ep_aggr);
		if (ep_aggr.aggr_en) {
			res = ipa3_tag_aggr_force_close(clnt_hdl);
			if (res) {
			IPAERR("tag process timeout, client:%d err:%d\n",
				IPAERR("tag process timeout client:%d err:%d\n",
					clnt_hdl, res);
			BUG();
				ipa_assert();
			}
		}
	}

@@ -1257,10 +1267,12 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
		goto disable_clk_and_exit;
	}

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		/* Suspend the DL/DPL EP */
		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
		ep_cfg_ctrl.ipa_ep_suspend = true;
		ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl);
	}

	/*
	 * Check if DL/DPL channel is empty again, data could enter the channel
@@ -1303,10 +1315,12 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
start_dl_and_exit:
	gsi_start_channel(dl_ep->gsi_chan_hdl);
unsuspend_dl_and_exit:
	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		/* Unsuspend the DL EP */
		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
		ep_cfg_ctrl.ipa_ep_suspend = false;
		ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl);
	}
disable_clk_and_exit:
	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(dl_clnt_hdl));
	return result;
@@ -1371,10 +1385,12 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl)
		ul_ep = &ipa3_ctx->ep[ul_clnt_hdl];
	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(dl_clnt_hdl));

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		/* Unsuspend the DL/DPL EP */
		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
		ep_cfg_ctrl.ipa_ep_suspend = false;
		ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl);
	}

	/* Start DL channel */
	gsi_res = gsi_start_channel(dl_ep->gsi_chan_hdl);
+0 −2
Original line number Diff line number Diff line
@@ -1970,8 +1970,6 @@ 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);
void ipa3_suspend_apps_pipes(bool suspend);
void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable,
			uint32_t qmap_id);
int ipa3_flt_read_tbl_from_hw(u32 pipe_idx,
	enum ipa_ip_type ip_type,
	bool hashable,
+9 −7
Original line number Diff line number Diff line
@@ -1600,13 +1600,15 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl)

	memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
	if (IPA_CLIENT_IS_CONS(ep->client)) {
		if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
			ep_cfg_ctrl.ipa_ep_suspend = true;
			result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
			if (result)
			IPAERR("client (ep: %d) failed to suspend result=%d\n",
				IPAERR("(ep: %d) failed to suspend result=%d\n",
						clnt_hdl, result);
			else
			IPADBG("client (ep: %d) suspended\n", clnt_hdl);
				IPADBG("(ep: %d) suspended\n", clnt_hdl);
		}
	} else {
		ep_cfg_ctrl.ipa_ep_delay = true;
		result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
+118 −2
Original line number Diff line number Diff line
@@ -1631,6 +1631,16 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client)

	ep = &ipa3_ctx->ep[ipa_ep_idx];

	/*
	 * starting IPA 4.0 pipe no longer can be suspended. Instead,
	 * the corresponding GSI channel should be stopped. Usually client
	 * driver will take care of stopping the channel. For client drivers
	 * that are not stopping the channel, IPA RM will do that based on
	 * ipa3_should_pipe_channel_be_stopped().
	 */
	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
		return false;

	if (ep->keep_ipa_awake)
		return false;

@@ -1650,6 +1660,41 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client)
	return false;
}

/**
 * ipa3_should_pipe_channel_be_stopped() - returns true when the client's
 * channel should be stopped during a power save scenario. False otherwise.
 * Most client already stops the GSI channel on suspend, and are not included
 * in the list below.
 *
 * @client: [IN] IPA client
 */
static bool ipa3_should_pipe_channel_be_stopped(enum ipa_client_type client)
{
	struct ipa3_ep_context *ep;
	int ipa_ep_idx;

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
		return false;

	ipa_ep_idx = ipa3_get_ep_mapping(client);
	if (ipa_ep_idx == -1) {
		IPAERR("Invalid client.\n");
		WARN_ON(1);
		return false;
	}

	ep = &ipa3_ctx->ep[ipa_ep_idx];

	if (ep->keep_ipa_awake)
		return false;

	if (client == IPA_CLIENT_ODU_EMB_CONS ||
	    client == IPA_CLIENT_ODU_TETH_CONS)
		return true;

	return false;
}

/**
 * ipa3_suspend_resource_sync() - suspend client endpoints related to the IPA_RM
 * resource and decrement active clients counter, which may result in clock
@@ -1695,6 +1740,19 @@ int ipa3_suspend_resource_sync(enum ipa_rm_resource_name resource)
				pipe_suspended = true;
			}
		}

		if (ipa3_ctx->ep[ipa_ep_idx].client == client &&
			ipa3_should_pipe_channel_be_stopped(client)) {
			if (ipa3_ctx->ep[ipa_ep_idx].valid) {
				/* Stop GSI channel */
				res = ipa3_stop_gsi_channel(ipa_ep_idx);
				if (res) {
					IPAERR("failed stop gsi ch %lu\n",
					ipa3_ctx->ep[ipa_ep_idx].gsi_chan_hdl);
					return res;
				}
			}
		}
	}
	/* Sleep ~1 msec */
	if (pipe_suspended)
@@ -1761,6 +1819,12 @@ int ipa3_suspend_resource_no_block(enum ipa_rm_resource_name resource)
				ipa3_cfg_ep_ctrl(ipa_ep_idx, &suspend);
			}
		}

		if (ipa3_ctx->ep[ipa_ep_idx].client == client &&
			ipa3_should_pipe_channel_be_stopped(client)) {
			res = -EPERM;
			goto bail;
		}
	}

	if (res == 0) {
@@ -1824,6 +1888,19 @@ int ipa3_resume_resource(enum ipa_rm_resource_name resource)
				ipa3_cfg_ep_ctrl(ipa_ep_idx, &suspend);
			}
		}

		if (ipa3_ctx->ep[ipa_ep_idx].client == client &&
			ipa3_should_pipe_channel_be_stopped(client)) {
			if (ipa3_ctx->ep[ipa_ep_idx].valid) {
				res = gsi_start_channel(
					ipa3_ctx->ep[ipa_ep_idx].gsi_chan_hdl);
				if (res) {
					IPAERR("failed to start gsi ch %lu\n",
					ipa3_ctx->ep[ipa_ep_idx].gsi_chan_hdl);
					return res;
				}
			}
		}
	}

	return res;
@@ -2714,6 +2791,12 @@ int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl)
		return -EINVAL;
	}

	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0 && ep_ctrl->ipa_ep_suspend) {
		IPAERR("pipe suspend is not supported\n");
		WARN_ON(1);
		return -EPERM;
	}

	IPADBG("pipe=%d ep_suspend=%d, ep_delay=%d\n",
		clnt_hdl,
		ep_ctrl->ipa_ep_suspend,
@@ -4674,6 +4757,7 @@ void ipa3_suspend_apps_pipes(bool suspend)
	struct ipa_ep_cfg_ctrl cfg;
	int ipa_ep_idx;
	struct ipa3_ep_context *ep;
	int res;

	memset(&cfg, 0, sizeof(cfg));
	cfg.ipa_ep_suspend = suspend;
@@ -4688,7 +4772,23 @@ void ipa3_suspend_apps_pipes(bool suspend)
	if (ep->valid) {
		IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend",
			ipa_ep_idx);
		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
			if (suspend) {
				res = ipa3_stop_gsi_channel(ipa_ep_idx);
				if (res) {
					IPAERR("failed to stop LAN channel\n");
					ipa_assert();
				}
			} else {
				res = gsi_start_channel(ep->gsi_chan_hdl);
				if (res) {
					IPAERR("failed to start LAN channel\n");
					ipa_assert();
				}
			}
		} else {
			ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg);
		}
		if (suspend)
			ipa3_gsi_poll_after_suspend(ep);
		else if (!atomic_read(&ep->sys->curr_polling_state))
@@ -4706,7 +4806,23 @@ void ipa3_suspend_apps_pipes(bool suspend)
	if (ep->valid) {
		IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend",
			ipa_ep_idx);
		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
			if (suspend) {
				res = ipa3_stop_gsi_channel(ipa_ep_idx);
				if (res) {
					IPAERR("failed to stop WAN channel\n");
					ipa_assert();
				}
			} else {
				res = gsi_start_channel(ep->gsi_chan_hdl);
				if (res) {
					IPAERR("failed to start WAN channel\n");
					ipa_assert();
				}
			}
		} else {
			ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg);
		}
		if (suspend)
			ipa3_gsi_poll_after_suspend(ep);
		else if (!atomic_read(&ep->sys->curr_polling_state))
Loading