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

Commit c8ebc0e7 authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: changes to suspend/disable for WDI 2" into msm-4.9

parents 0d391f34 dabdca7e
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, 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
@@ -95,6 +95,46 @@ int ipa_disable_data_path(u32 clnt_hdl)
	return res;
}

int ipa2_enable_force_clear(u32 request_id, bool throttle_source,
	u32 source_pipe_bitmask)
{
	struct ipa_enable_force_clear_datapath_req_msg_v01 req;
	int result;

	memset(&req, 0, sizeof(req));
	req.request_id = request_id;
	req.source_pipe_bitmask = source_pipe_bitmask;
	if (throttle_source) {
		req.throttle_source_valid = 1;
		req.throttle_source = 1;
	}
	result = qmi_enable_force_clear_datapath_send(&req);
	if (result) {
		IPAERR("qmi_enable_force_clear_datapath_send failed %d\n",
			result);
		return result;
	}

	return 0;
}

int ipa2_disable_force_clear(u32 request_id)
{
	struct ipa_disable_force_clear_datapath_req_msg_v01 req;
	int result;

	memset(&req, 0, sizeof(req));
	req.request_id = request_id;
	result = qmi_disable_force_clear_datapath_send(&req);
	if (result) {
		IPAERR("qmi_disable_force_clear_datapath_send failed %d\n",
			result);
		return result;
	}

	return 0;
}

static int ipa2_smmu_map_peer_bam(unsigned long dev)
{
	phys_addr_t base;
+3 −0
Original line number Diff line number Diff line
@@ -1772,6 +1772,9 @@ void ipa_delete_dflt_flt_rules(u32 ipa_ep_idx);

int ipa_enable_data_path(u32 clnt_hdl);
int ipa_disable_data_path(u32 clnt_hdl);
int ipa2_enable_force_clear(u32 request_id, bool throttle_source,
	u32 source_pipe_bitmask);
int ipa2_disable_force_clear(u32 request_id);
int ipa_id_alloc(void *ptr);
void *ipa_id_find(u32 id);
void ipa_id_remove(u32 id);
+6 −2
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000
#define QMI_SEND_REQ_TIMEOUT_MS 60000

#define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000

static struct qmi_handle *ipa_svc_handle;
static void ipa_a5_svc_recv_msg(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_recv_msg, ipa_a5_svc_recv_msg);
@@ -583,7 +585,8 @@ int qmi_enable_force_clear_datapath_send(
			&req_desc,
			req,
			sizeof(*req),
			&resp_desc, &resp, sizeof(resp), 0);
			&resp_desc, &resp, sizeof(resp),
			QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
	if (rc < 0) {
		IPAWANERR("send req failed %d\n", rc);
		return rc;
@@ -628,7 +631,8 @@ int qmi_disable_force_clear_datapath_send(
			&req_desc,
			req,
			sizeof(*req),
			&resp_desc, &resp, sizeof(resp), 0);
			&resp_desc, &resp, sizeof(resp),
			QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
	if (rc < 0) {
		IPAWANERR("send req failed %d\n", rc);
		return rc;
+36 −23
Original line number Diff line number Diff line
@@ -1404,7 +1404,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
	union IpaHwWdiCommonChCmdData_t disable;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 prod_hdl;
	int i;

	if (unlikely(!ipa_ctx)) {
		IPAERR("IPA driver was not initialized\n");
@@ -1421,28 +1420,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
	if (result)
		return result;

	/* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */
	if (ipa_ctx->ipa_wdi2) {
		for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
			IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n",
					i,
					*ipa_ctx->uc_ctx.rdy_ring_rp_va,
					*ipa_ctx->uc_ctx.rdy_comp_ring_wp_va);
			if (*ipa_ctx->uc_ctx.rdy_ring_rp_va !=
				*ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) {
				usleep_range(IPA_UC_WAIT_MIN_SLEEP,
					IPA_UC_WAII_MAX_SLEEP);
			} else {
				break;
			}
		}
		/* In case ipa_uc still haven't processed all
		 * pending descriptors, we have to assert
		 */
		if (i == IPA_UC_FINISH_MAX)
			ipa_assert();
	}

	IPADBG("ep=%d\n", clnt_hdl);

	ep = &ipa_ctx->ep[clnt_hdl];
@@ -1468,7 +1445,13 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
	 * holb on IPA Producer pipe
	 */
	if (IPA_CLIENT_IS_PROD(ep->client)) {

		IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n",
			clnt_hdl, ep->client);

		/* remove delay on wlan-prod pipe*/
		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));

		ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);

		prod_hdl = ipa2_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
@@ -1594,6 +1577,8 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
	struct ipa_ep_context *ep;
	union IpaHwWdiCommonChCmdData_t suspend;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 source_pipe_bitmask = 0;
	bool disable_force_clear = false;

	if (unlikely(!ipa_ctx)) {
		IPAERR("IPA driver was not initialized\n");
@@ -1623,6 +1608,31 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
	suspend.params.ipa_pipe_number = clnt_hdl;

	if (IPA_CLIENT_IS_PROD(ep->client)) {
		/*
		 * For WDI 2.0 need to ensure pipe will be empty before suspend
		 * as IPA uC will fail to suspend the pipe otherwise.
		 */
		if (ipa_ctx->ipa_wdi2) {
			source_pipe_bitmask = 1 <<
				ipa_get_ep_mapping(ep->client);
			result = ipa2_enable_force_clear(clnt_hdl,
				false, source_pipe_bitmask);
			if (result) {
				/*
				 * assuming here modem SSR, AP can remove
				 * the delay in this case
				 */
				IPAERR("failed to force clear %d\n", result);
				IPAERR("remove delay from SCND reg\n");
				memset(&ep_cfg_ctrl, 0,
					sizeof(struct ipa_ep_cfg_ctrl));
				ep_cfg_ctrl.ipa_ep_delay = false;
				ep_cfg_ctrl.ipa_ep_suspend = false;
				ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
			} else {
				disable_force_clear = true;
			}
		}
		IPADBG("Post suspend event first for IPA Producer\n");
		IPADBG("Client: %d clnt_hdl: %d\n", ep->client, clnt_hdl);
		result = ipa_uc_send_cmd(suspend.raw32b,
@@ -1667,6 +1677,9 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
		}
	}

	if (disable_force_clear)
		ipa2_disable_force_clear(clnt_hdl);

	ipa_ctx->tag_process_before_gating = true;
	IPA_ACTIVE_CLIENTS_DEC_EP(ipa2_get_client_mapping(clnt_hdl));
	ep->uc_offload_state &= ~IPA_WDI_RESUMED;