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

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

Merge "msm: ipa: allow abort for disable_clks"

parents a248b15b 45582828
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@
#include "ipa_trace.h"
#include "ipa_odl.h"

#define IPA_SUSPEND_BUSY_TIMEOUT (msecs_to_jiffies(10))

/*
 * The following for adding code (ie. for EMULATION) not found on x86.
 */
@@ -118,7 +120,7 @@ static void ipa3_load_ipa_fw(struct work_struct *work);
static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw);

static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work);
static DECLARE_WORK(ipa_dec_clients_disable_clks_on_wq_work,
static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work,
	ipa_dec_clients_disable_clks_on_wq);

static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg);
@@ -4811,8 +4813,16 @@ static void __ipa3_dec_client_disable_clks(void)
	ret = atomic_sub_return(1, &ipa3_ctx->ipa3_active_clients.cnt);
	if (ret > 0)
		goto unlock_mutex;
	ipa3_suspend_apps_pipes(true);
	ret = ipa3_suspend_apps_pipes(true);
	if (ret) {
		/* HW is busy, retry after some time */
		atomic_inc(&ipa3_ctx->ipa3_active_clients.cnt);
		queue_delayed_work(ipa3_ctx->power_mgmt_wq,
			&ipa_dec_clients_disable_clks_on_wq_work,
			IPA_SUSPEND_BUSY_TIMEOUT);
	} else {
		ipa3_disable_clks();
	}

unlock_mutex:
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
@@ -4865,8 +4875,8 @@ void ipa3_dec_client_disable_clks_no_block(
	}

	/* seems like this is the only client holding the clocks */
	queue_work(ipa3_ctx->power_mgmt_wq,
		&ipa_dec_clients_disable_clks_on_wq_work);
	queue_delayed_work(ipa3_ctx->power_mgmt_wq,
		&ipa_dec_clients_disable_clks_on_wq_work, 0);
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -2915,7 +2915,7 @@ int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info);
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);
int ipa3_suspend_apps_pipes(bool suspend);
int ipa3_flt_read_tbl_from_hw(u32 pipe_idx,
	enum ipa_ip_type ip_type,
	bool hashable,
+58 −122
Original line number Diff line number Diff line
@@ -7486,12 +7486,10 @@ void ipa3_set_resorce_groups_min_max_limits(void)
	IPADBG("EXIT\n");
}

static void ipa3_gsi_poll_after_suspend(struct ipa3_ep_context *ep)
static bool ipa3_gsi_channel_is_quite(struct ipa3_ep_context *ep)
{
	bool empty;

	IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl);
	gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL);
	gsi_is_channel_empty(ep->gsi_chan_hdl, &empty);
	if (!empty) {
		IPADBG("ch %ld not empty\n", ep->gsi_chan_hdl);
@@ -7500,6 +7498,7 @@ static void ipa3_gsi_poll_after_suspend(struct ipa3_ep_context *ep)
		if (!atomic_read(&ep->sys->curr_polling_state))
			__ipa_gsi_irq_rx_scedule_poll(ep->sys);
	}
	return empty;
}

static int __ipa3_stop_gsi_channel(u32 clnt_hdl)
@@ -7625,26 +7624,28 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl)
	return res;
}

void ipa3_suspend_apps_pipes(bool suspend)
static int _ipa_suspend_pipe(enum ipa_client_type client, 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;
	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
		IPAERR("not supported\n");
		return -EPERM;
	}

	ipa_ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS);
	ipa_ep_idx = ipa3_get_ep_mapping(client);
	if (ipa_ep_idx < 0) {
		IPAERR("IPA client mapping failed\n");
		ipa_assert();
		return;
		IPADBG("client %d not configued\n", client);
		return 0;
	}

	ep = &ipa3_ctx->ep[ipa_ep_idx];
	if (ep->valid) {
		IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend",
			ipa_ep_idx);
	if (!ep->valid)
		return 0;

	IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", ipa_ep_idx);
	/*
	 * move the channel to callback mode.
	 * This needs to happen before starting the channel to make
@@ -7654,7 +7655,6 @@ void ipa3_suspend_apps_pipes(bool suspend)
		gsi_config_channel_mode(ep->gsi_chan_hdl,
					GSI_CHAN_MODE_CALLBACK);

		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
	if (suspend) {
		res = __ipa3_stop_gsi_channel(ipa_ep_idx);
		if (res) {
@@ -7668,98 +7668,34 @@ void ipa3_suspend_apps_pipes(bool suspend)
			ipa_assert();
		}
	}
		} else {
			ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg);
		}
		if (suspend)
			ipa3_gsi_poll_after_suspend(ep);
	}

	ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS);
	/* Considering the case for SSR. */
	if (ipa_ep_idx == -1) {
		IPADBG("Invalid mapping for IPA_CLIENT_APPS_WAN_CONS\n");
		return;
	}
	ep = &ipa3_ctx->ep[ipa_ep_idx];
	if (ep->valid) {
		IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend",
			ipa_ep_idx);
		/*
		 * move the channel to callback mode.
		 * This needs to happen before starting the channel to make
		 * sure we don't loose any interrupt
		 */
		if (!suspend && !atomic_read(&ep->sys->curr_polling_state))
			gsi_config_channel_mode(ep->gsi_chan_hdl,
				GSI_CHAN_MODE_CALLBACK);
		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 if (!atomic_read(&ipa3_ctx->is_ssr)) {
				/* If SSR was alreday started not required to
				 * start WAN channel,Because in SSR will stop
				 * channel and reset the channel.
				 */
				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);
	}

	ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_ODL_DPL_CONS);
	/* Considering the case for SSR. */
	if (ipa_ep_idx == -1) {
		IPADBG("Invalid mapping for IPA_CLIENT_ODL_DPL_CONS\n");
		return;
	}
	ep = &ipa3_ctx->ep[ipa_ep_idx];
	if (ep->valid) {
		IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend",
			ipa_ep_idx);
		/*
		 * move the channel to callback mode.
		 * This needs to happen before starting the channel to make
		 * sure we don't loose any interrupt
		 */
		if (!suspend && !atomic_read(&ep->sys->curr_polling_state))
		IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl);
		gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL);
		if (!ipa3_gsi_channel_is_quite(ep))
			return -EAGAIN;
	} else if (!atomic_read(&ep->sys->curr_polling_state)) {
		IPADBG("switch ch %ld to callback\n", ep->gsi_chan_hdl);
		gsi_config_channel_mode(ep->gsi_chan_hdl,
			GSI_CHAN_MODE_CALLBACK);
		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 ODL channel\n");
					ipa_assert();
	}
			} else if (!atomic_read(&ipa3_ctx->is_ssr)) {
				/* If SSR was alreday started not required to
				 * start WAN channel,Because in SSR will stop
				 * channel and reset the channel.
				 */
				res = gsi_start_channel(ep->gsi_chan_hdl);
				if (res) {
					IPAERR("failed to start ODL channel\n");
					ipa_assert();
				}
			}
		} else {
			ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg);
		}
		if (suspend)
			ipa3_gsi_poll_after_suspend(ep);

	return 0;
}

int ipa3_suspend_apps_pipes(bool suspend)
{
	int res;

	res = _ipa_suspend_pipe(IPA_CLIENT_APPS_LAN_CONS, suspend);
	if (res)
		return res;

	res = _ipa_suspend_pipe(IPA_CLIENT_APPS_WAN_CONS, suspend);
	if (res)
		return res;

	return 0;
}

int ipa3_allocate_dma_task_for_gsi(void)