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

Commit 20d46786 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa4: remove IPA_ENDP_INIT_CTRL_n.ENDP_SUSPEND usage"

parents 3d57149b a699afd8
Loading
Loading
Loading
Loading
+26 −180
Original line number Diff line number Diff line
/* Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-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
@@ -125,7 +125,6 @@ enum ipa3_usb_state {
	IPA_USB_CONNECTED,
	IPA_USB_STOPPED,
	IPA_USB_SUSPEND_REQUESTED,
	IPA_USB_SUSPEND_IN_PROGRESS,
	IPA_USB_SUSPENDED,
	IPA_USB_SUSPENDED_NO_RWAKEUP,
	IPA_USB_RESUME_IN_PROGRESS
@@ -146,13 +145,6 @@ enum ipa3_usb_transport_type {
#define IPA3_USB_IS_TTYPE_DPL(__ttype) \
	((__ttype) == IPA_USB_TRANSPORT_DPL)

struct finish_suspend_work_context {
	struct work_struct work;
	enum ipa3_usb_transport_type ttype;
	u32 dl_clnt_hdl;
	u32 ul_clnt_hdl;
};

struct ipa3_usb_teth_prot_conn_params {
	u32 usb_to_ipa_clnt_hdl;
	u32 ipa_to_usb_clnt_hdl;
@@ -168,7 +160,6 @@ struct ipa3_usb_transport_type_ctx {
	int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *user_data);
	void *user_data;
	enum ipa3_usb_state state;
	struct finish_suspend_work_context finish_suspend_work;
	struct ipa_usb_xdci_chan_params ch_params;
	struct ipa3_usb_teth_prot_conn_params teth_conn_params;
};
@@ -221,16 +212,10 @@ struct ipa3_usb_status_dbg_info {

static void ipa3_usb_wq_notify_remote_wakeup(struct work_struct *work);
static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work);
static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work);
static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work);
static DECLARE_WORK(ipa3_usb_notify_remote_wakeup_work,
	ipa3_usb_wq_notify_remote_wakeup);
static DECLARE_WORK(ipa3_usb_dpl_notify_remote_wakeup_work,
	ipa3_usb_wq_dpl_notify_remote_wakeup);
static DECLARE_WORK(ipa3_usb_notify_suspend_completed_work,
	ipa3_usb_wq_notify_suspend_completed);
static DECLARE_WORK(ipa3_usb_dpl_notify_suspend_completed_work,
	ipa3_usb_wq_dpl_notify_suspend_completed);

struct ipa3_usb_context *ipa3_usb_ctx;

@@ -273,8 +258,6 @@ static char *ipa3_usb_state_to_string(enum ipa3_usb_state state)
		return "IPA_USB_STOPPED";
	case IPA_USB_SUSPEND_REQUESTED:
		return "IPA_USB_SUSPEND_REQUESTED";
	case IPA_USB_SUSPEND_IN_PROGRESS:
		return "IPA_USB_SUSPEND_IN_PROGRESS";
	case IPA_USB_SUSPENDED:
		return "IPA_USB_SUSPENDED";
	case IPA_USB_SUSPENDED_NO_RWAKEUP:
@@ -330,17 +313,11 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit,
			 * In case of failure during suspend request
			 * handling, state is reverted to connected.
			 */
			(err_permit && state == IPA_USB_SUSPEND_REQUESTED) ||
			/*
			 * In case of failure during suspend completing
			 * handling, state is reverted to connected.
			 */
			(err_permit && state == IPA_USB_SUSPEND_IN_PROGRESS))
			(err_permit && state == IPA_USB_SUSPEND_REQUESTED))
			state_legal = true;
		break;
	case IPA_USB_STOPPED:
		if (state == IPA_USB_SUSPEND_IN_PROGRESS ||
			state == IPA_USB_CONNECTED ||
		if (state == IPA_USB_CONNECTED ||
			state == IPA_USB_SUSPENDED ||
			state == IPA_USB_SUSPENDED_NO_RWAKEUP)
			state_legal = true;
@@ -349,19 +326,8 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit,
		if (state == IPA_USB_CONNECTED)
			state_legal = true;
		break;
	case IPA_USB_SUSPEND_IN_PROGRESS:
		if (state == IPA_USB_SUSPEND_REQUESTED ||
			/*
			 * In case of failure during resume, state is reverted
			 * to original, which could be suspend_in_progress.
			 * Allow it.
			 */
			(err_permit && state == IPA_USB_RESUME_IN_PROGRESS))
			state_legal = true;
		break;
	case IPA_USB_SUSPENDED:
		if (state == IPA_USB_SUSPEND_REQUESTED ||
			state == IPA_USB_SUSPEND_IN_PROGRESS ||
			/*
			 * In case of failure during resume, state is reverted
			 * to original, which could be suspended. Allow it
@@ -374,8 +340,7 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit,
			state_legal = true;
		break;
	case IPA_USB_RESUME_IN_PROGRESS:
		if (state == IPA_USB_SUSPEND_IN_PROGRESS ||
			state == IPA_USB_SUSPENDED)
		if (state == IPA_USB_SUSPENDED)
			state_legal = true;
		break;
	default:
@@ -452,7 +417,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op,
		break;
	case IPA_USB_OP_DISCONNECT:
		if  (state == IPA_USB_CONNECTED ||
			state == IPA_USB_SUSPEND_IN_PROGRESS ||
			state == IPA_USB_SUSPENDED ||
			state == IPA_USB_SUSPENDED_NO_RWAKEUP)
			is_legal = true;
@@ -483,7 +447,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op,
		break;
	case IPA_USB_OP_RESUME:
		if (state == IPA_USB_SUSPENDED ||
			state == IPA_USB_SUSPEND_IN_PROGRESS ||
			state == IPA_USB_SUSPENDED_NO_RWAKEUP)
			is_legal = true;
		break;
@@ -582,71 +545,6 @@ static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work)
	ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_REMOTE_WAKEUP);
}

static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work)
{
	ipa3_usb_notify_do(IPA_USB_TRANSPORT_TETH, IPA_USB_SUSPEND_COMPLETED);
}

static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work)
{
	ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_SUSPEND_COMPLETED);
}

static void ipa3_usb_wq_finish_suspend_work(struct work_struct *work)
{
	struct finish_suspend_work_context *finish_suspend_work_ctx;
	unsigned long flags;
	int result = -EFAULT;
	struct ipa3_usb_transport_type_ctx *tctx;

	mutex_lock(&ipa3_usb_ctx->general_mutex);
	IPA_USB_DBG_LOW("entry\n");
	finish_suspend_work_ctx = container_of(work,
		struct finish_suspend_work_context, work);
	tctx = &ipa3_usb_ctx->ttype_ctx[finish_suspend_work_ctx->ttype];

	spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags);
	if (tctx->state != IPA_USB_SUSPEND_IN_PROGRESS) {
		spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);
		mutex_unlock(&ipa3_usb_ctx->general_mutex);
		return;
	}
	spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);

	/* Stop DL/DPL channel */
	result = ipa3_stop_gsi_channel(finish_suspend_work_ctx->dl_clnt_hdl);
	if (result) {
		IPAERR("Error stopping DL/DPL channel: %d, resuming channel\n",
			result);
		ipa3_xdci_resume(finish_suspend_work_ctx->ul_clnt_hdl,
			finish_suspend_work_ctx->dl_clnt_hdl,
			IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype));
		/* Change state back to CONNECTED */
		if (!ipa3_usb_set_state(IPA_USB_CONNECTED, true,
			finish_suspend_work_ctx->ttype))
			IPA_USB_ERR("failed to change state to connected\n");
		queue_work(ipa3_usb_ctx->wq,
			IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ?
			&ipa3_usb_dpl_notify_remote_wakeup_work :
			&ipa3_usb_notify_remote_wakeup_work);
		mutex_unlock(&ipa3_usb_ctx->general_mutex);
		return;
	}

	/* Change ipa_usb state to SUSPENDED */
	if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false,
		finish_suspend_work_ctx->ttype))
		IPA_USB_ERR("failed to change state to suspended\n");

	queue_work(ipa3_usb_ctx->wq,
		IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ?
		&ipa3_usb_dpl_notify_suspend_completed_work :
		&ipa3_usb_notify_suspend_completed_work);

	IPA_USB_DBG_LOW("exit\n");
	mutex_unlock(&ipa3_usb_ctx->general_mutex);
}

static int ipa3_usb_cons_request_resource_cb_do(
	enum ipa3_usb_transport_type ttype,
	struct work_struct *remote_wakeup_work)
@@ -674,17 +572,6 @@ static int ipa3_usb_cons_request_resource_cb_do(
		else
			result = -EINPROGRESS;
		break;
	case IPA_USB_SUSPEND_IN_PROGRESS:
		/*
		 * This case happens due to suspend interrupt.
		 * CONS is granted
		 */
		if (!rm_ctx->cons_requested) {
			rm_ctx->cons_requested = true;
			queue_work(ipa3_usb_ctx->wq, remote_wakeup_work);
		}
		result = 0;
		break;
	case IPA_USB_SUSPENDED:
		if (!rm_ctx->cons_requested) {
			rm_ctx->cons_requested = true;
@@ -727,15 +614,10 @@ static int ipa3_usb_cons_release_resource_cb_do(
			ipa3_usb_state_to_string(
			ipa3_usb_ctx->ttype_ctx[ttype].state));
	switch (ipa3_usb_ctx->ttype_ctx[ttype].state) {
	case IPA_USB_SUSPEND_IN_PROGRESS:
	case IPA_USB_SUSPENDED:
		/* Proceed with the suspend if no DL/DPL data */
		if (rm_ctx->cons_requested)
			rm_ctx->cons_requested_released = true;
		else {
			queue_work(ipa3_usb_ctx->wq,
				&ipa3_usb_ctx->ttype_ctx[ttype].
				finish_suspend_work.work);
		}
		break;
	case IPA_USB_SUSPEND_REQUESTED:
		if (rm_ctx->cons_requested)
@@ -2311,8 +2193,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags);
	orig_state = ipa3_usb_ctx->ttype_ctx[ttype].state;
	if (!IPA3_USB_IS_TTYPE_DPL(ttype)) {
		if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS &&
			orig_state != IPA_USB_SUSPENDED) {
		if (orig_state != IPA_USB_SUSPENDED) {
			spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock,
				flags);
			/* Stop UL channel */
@@ -2340,8 +2221,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	if (result)
		goto bad_params;

	if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS &&
		orig_state != IPA_USB_SUSPENDED) {
	if (orig_state != IPA_USB_SUSPENDED) {
		result = ipa3_usb_release_prod(ttype);
		if (result) {
			IPA_USB_ERR("failed to release PROD.\n");
@@ -2547,7 +2427,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
{
	int result = 0;
	unsigned long flags;
	enum ipa3_usb_cons_state curr_cons_state;
	enum ipa3_usb_transport_type ttype;

	mutex_lock(&ipa3_usb_ctx->general_mutex);
@@ -2602,20 +2481,13 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
		goto release_prod_fail;
	}

	spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags);
	curr_cons_state = ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state;
	spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);
	if (curr_cons_state == IPA_USB_CONS_GRANTED) {
		/* Change state to SUSPEND_IN_PROGRESS */
		if (!ipa3_usb_set_state(IPA_USB_SUSPEND_IN_PROGRESS,
			false, ttype))
			IPA_USB_ERR("fail set state to suspend_in_progress\n");

	/* Check if DL/DPL data pending */
	spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags);
		if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) {
			IPA_USB_DBG(
				"DL/DPL data pending, invoke remote wakeup\n");
	if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state ==
		IPA_USB_CONS_GRANTED &&
		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) {

		IPA_USB_DBG("DL/DPL data pending, invoke remote wakeup\n");
		queue_work(ipa3_usb_ctx->wq,
			IPA3_USB_IS_TTYPE_DPL(ttype) ?
			&ipa3_usb_dpl_notify_remote_wakeup_work :
@@ -2623,28 +2495,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	}
	spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);

		ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ttype =
			ttype;
		ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.dl_clnt_hdl =
			dl_clnt_hdl;
		ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ul_clnt_hdl =
			ul_clnt_hdl;
		INIT_WORK(&ipa3_usb_ctx->ttype_ctx[ttype].
			finish_suspend_work.work,
			ipa3_usb_wq_finish_suspend_work);

		result = -EINPROGRESS;
		IPA_USB_DBG("exit with suspend_in_progress\n");
		goto bad_params;
	}

	/* Stop DL channel */
	result = ipa3_stop_gsi_channel(dl_clnt_hdl);
	if (result) {
		IPAERR("Error stopping DL/DPL channel: %d\n", result);
		result = -EFAULT;
		goto release_prod_fail;
	}
	/* Change state to SUSPENDED */
	if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, ttype))
		IPA_USB_ERR("failed to change state to suspended\n");
@@ -2803,14 +2653,12 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
		}
	}

	if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) {
	/* Start DL/DPL channel */
	result = ipa3_start_gsi_channel(dl_clnt_hdl);
	if (result) {
		IPA_USB_ERR("failed to start DL/DPL channel.\n");
		goto start_dl_fail;
	}
	}

	/* Change state to CONNECTED */
	if (!ipa3_usb_set_state(IPA_USB_CONNECTED, false, ttype)) {
@@ -2824,12 +2672,10 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	return 0;

state_change_connected_fail:
	if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) {
	result = ipa3_stop_gsi_channel(dl_clnt_hdl);
	if (result)
		IPA_USB_ERR("Error stopping DL/DPL channel: %d\n",
			result);
	}
start_dl_fail:
	if (!IPA3_USB_IS_TTYPE_DPL(ttype)) {
		result = ipa3_stop_gsi_channel(ul_clnt_hdl);
+5 −60
Original line number Diff line number Diff line
@@ -498,63 +498,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) {
@@ -1866,6 +1809,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);
+78 −46
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
@@ -1275,6 +1287,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
		goto unsuspend_dl_and_exit;
	}

	/* Stop DL channel */
	result = ipa3_stop_gsi_channel(dl_clnt_hdl);
	if (result) {
		IPAERR("Error stopping DL/DPL channel: %d\n", result);
		result = -EFAULT;
		goto unsuspend_dl_and_exit;
	}

	/* STOP UL channel */
	if (!is_dpl) {
		source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ul_ep->client);
@@ -1283,7 +1303,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
		if (result) {
			IPAERR("Error stopping UL channel: result = %d\n",
				result);
			goto unsuspend_dl_and_exit;
			goto start_dl_and_exit;
		}
	}

@@ -1292,11 +1312,15 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	IPADBG("exit\n");
	return 0;

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;
@@ -1340,7 +1364,8 @@ int ipa3_start_gsi_channel(u32 clnt_hdl)

int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl)
{
	struct ipa3_ep_context *ul_ep, *dl_ep;
	struct ipa3_ep_context *ul_ep = NULL;
	struct ipa3_ep_context *dl_ep = NULL;
	enum gsi_status gsi_res;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;

@@ -1360,10 +1385,17 @@ 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);
	if (gsi_res != GSI_STATUS_SUCCESS)
		IPAERR("Error starting DL channel: %d\n", gsi_res);

	/* Start UL channel */
	if (!is_dpl) {
+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);
Loading