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

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

Merge "msm: ipa: optimizations to enable / disable clocks"

parents 01e81c03 242952bb
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -623,7 +623,6 @@ void __init mem_init(void)
#undef MLM
#undef MLK_ROUNDUP

#ifdef CONFIG_ARM_KERNMEM_PERMS
struct section_perm {
	const char *name;
	unsigned long start;
+118 −66
Original line number Diff line number Diff line
@@ -235,6 +235,10 @@ static void ipa_gsi_notify_cb(struct gsi_per_notify *notify);
static void ipa3_post_init_wq(struct work_struct *work);
static DECLARE_WORK(ipa3_post_init_work, ipa3_post_init_wq);

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

static struct ipa3_plat_drv_res ipa3_res = {0, };
struct msm_bus_scale_pdata *ipa3_bus_scale_table;

@@ -314,7 +318,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size)
	}
	cnt += scnprintf(buf + cnt, size - cnt,
			"\nTotal active clients count: %d\n",
			ipa3_ctx->ipa3_active_clients.cnt);
			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));

	return cnt;
}
@@ -322,11 +326,11 @@ int ipa3_active_clients_log_print_table(char *buf, int size)
static int ipa3_active_clients_panic_notifier(struct notifier_block *this,
		unsigned long event, void *ptr)
{
	ipa3_active_clients_lock();
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	ipa3_active_clients_log_print_table(active_clients_table_buf,
			IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE);
	IPAERR("%s", active_clients_table_buf);
	ipa3_active_clients_unlock();
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);

	return NOTIFY_DONE;
}
@@ -395,11 +399,11 @@ static int ipa3_active_clients_log_init(void)

void ipa3_active_clients_log_clear(void)
{
	ipa3_active_clients_lock();
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	ipa3_ctx->ipa3_active_clients_logging.log_head = 0;
	ipa3_ctx->ipa3_active_clients_logging.log_tail =
			IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1;
	ipa3_active_clients_unlock();
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
}

static void ipa3_active_clients_log_destroy(void)
@@ -3267,7 +3271,6 @@ void _ipa_enable_clks_v3_0(void)
	}

	ipa3_uc_notify_clk_state(true);
	ipa3_suspend_apps_pipes(false);
}

static unsigned int ipa3_get_bus_vote(void)
@@ -3466,13 +3469,33 @@ void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id,
*/
void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
{
	ipa3_active_clients_lock();
	int ret;

	ipa3_active_clients_log_inc(id, false);
	ipa3_ctx->ipa3_active_clients.cnt++;
	if (ipa3_ctx->ipa3_active_clients.cnt == 1)
	ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt);
	if (ret) {
		IPADBG_LOW("active clients = %d\n",
			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
		return;
	}

	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);

	/* somebody might voted to clocks meanwhile */
	ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt);
	if (ret) {
		mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
		IPADBG_LOW("active clients = %d\n",
			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
		return;
	}

	ipa3_enable_clks();
	IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt);
	ipa3_active_clients_unlock();
	atomic_inc(&ipa3_ctx->ipa3_active_clients.cnt);
	IPADBG_LOW("active clients = %d\n",
		atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
	ipa3_suspend_apps_pipes(false);
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
}

/**
@@ -3486,23 +3509,57 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info
		*id)
{
	int res = 0;
	unsigned long flags;
	int ret;

	ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt);
	if (ret) {
		ipa3_active_clients_log_inc(id, true);
		IPADBG_LOW("active clients = %d\n",
			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
		return 0;
	}

	if (ipa3_active_clients_trylock(&flags) == 0)
	return -EPERM;
}

static void __ipa3_dec_client_disable_clks(void)
{
	int ret;

	if (!atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)) {
		IPAERR("trying to disable clocks with refcnt is 0!\n");
		ipa_assert();
		return;
	}

	if (ipa3_ctx->ipa3_active_clients.cnt == 0) {
		res = -EPERM;
	ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1);
	if (ret)
		goto bail;

	/* seems like this is the only client holding the clocks */
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) == 1 &&
	    ipa3_ctx->tag_process_before_gating) {
		ipa3_ctx->tag_process_before_gating = false;
		/*
		 * When TAG process ends, active clients will be
		 * decreased
		 */
		queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work);
		goto unlock_mutex;
	}
	ipa3_active_clients_log_inc(id, true);
	ipa3_ctx->ipa3_active_clients.cnt++;
	IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt);
bail:
	ipa3_active_clients_trylock_unlock(&flags);

	return res;
	/* a different context might increase the clock reference meanwhile */
	ret = atomic_sub_return(1, &ipa3_ctx->ipa3_active_clients.cnt);
	if (ret > 0)
		goto unlock_mutex;
	ipa3_disable_clks();

unlock_mutex:
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
bail:
	IPADBG_LOW("active clients = %d\n",
		atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
}

/**
@@ -3518,29 +3575,39 @@ int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info
 */
void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id)
{
	struct ipa_active_client_logging_info log_info;

	ipa3_active_clients_lock();
	ipa3_active_clients_log_dec(id, false);
	ipa3_ctx->ipa3_active_clients.cnt--;
	IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt);
	if (ipa3_ctx->ipa3_active_clients.cnt == 0) {
		if (ipa3_ctx->tag_process_before_gating) {
			ipa3_ctx->tag_process_before_gating = false;
			/*
			 * When TAG process ends, active clients will be
			 * decreased
			 */
			IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info,
					"TAG_PROCESS");
			ipa3_active_clients_log_inc(&log_info, false);
			ipa3_ctx->ipa3_active_clients.cnt = 1;
			queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work);
		} else {
			ipa3_disable_clks();
	__ipa3_dec_client_disable_clks();
}

static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work)
{
	__ipa3_dec_client_disable_clks();
}
	ipa3_active_clients_unlock();

/**
 * ipa3_dec_client_disable_clks_no_block() - Decrease active clients counter
 * if possible without blocking. If this is the last client then the desrease
 * will happen from work queue context.
 *
 * Return codes:
 * None
 */
void ipa3_dec_client_disable_clks_no_block(
	struct ipa_active_client_logging_info *id)
{
	int ret;

	ipa3_active_clients_log_dec(id, true);
	ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1);
	if (ret) {
		IPADBG_LOW("active clients = %d\n",
			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
		return;
	}

	/* 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);
}

/**
@@ -3636,34 +3703,20 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
		return 0;
	}

	ipa3_active_clients_lock();
	/* Hold the mutex to avoid race conditions with ipa3_enable_clocks() */
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	ipa3_ctx->curr_ipa_clk_rate = clk_rate;
	IPADBG_LOW("setting clock rate to %u\n", ipa3_ctx->curr_ipa_clk_rate);
	if (ipa3_ctx->ipa3_active_clients.cnt > 0) {
		struct ipa_active_client_logging_info log_info;

		/*
		 * clk_set_rate should be called with unlocked lock to allow
		 * clients to get a reference to IPA clock synchronously.
		 * Hold a reference to IPA clock here to make sure clock
		 * state does not change during set_rate.
		 */
		IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info);
		ipa3_ctx->ipa3_active_clients.cnt++;
		ipa3_active_clients_log_inc(&log_info, false);
		ipa3_active_clients_unlock();

	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) {
		if (ipa3_clk)
			clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate);
		if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
				ipa3_get_bus_vote()))
			WARN_ON(1);
		/* remove the vote added here */
		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
	} else {
		IPADBG_LOW("clocks are gated, not setting rate\n");
		ipa3_active_clients_unlock();
	}
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
	IPADBG_LOW("Done\n");

	return 0;
@@ -4625,10 +4678,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	}

	mutex_init(&ipa3_ctx->ipa3_active_clients.mutex);
	spin_lock_init(&ipa3_ctx->ipa3_active_clients.spinlock);
	IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE");
	ipa3_active_clients_log_inc(&log_info, false);
	ipa3_ctx->ipa3_active_clients.cnt = 1;
	atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1);

	/* Create workqueues for power management */
	ipa3_ctx->power_mgmt_wq =
+6 −6
Original line number Diff line number Diff line
@@ -363,14 +363,14 @@ static ssize_t ipa3_read_keep_awake(struct file *file, char __user *ubuf,
{
	int nbytes;

	ipa3_active_clients_lock();
	if (ipa3_ctx->ipa3_active_clients.cnt)
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt))
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"IPA APPS power state is ON\n");
	else
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"IPA APPS power state is OFF\n");
	ipa3_active_clients_unlock();
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);

	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
}
@@ -1064,7 +1064,7 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
		ipa3_ctx->stats.stat_compl,
		ipa3_ctx->stats.aggr_close,
		ipa3_ctx->stats.wan_aggr_close,
		ipa3_ctx->ipa3_active_clients.cnt,
		atomic_read(&ipa3_ctx->ipa3_active_clients.cnt),
		connect,
		ipa3_ctx->stats.wan_rx_empty,
		ipa3_ctx->stats.wan_repl_rx_empty,
@@ -1785,12 +1785,12 @@ static ssize_t ipa3_print_active_clients_log(struct file *file,
		return 0;
	}
	memset(active_clients_buf, 0, IPA_DBG_ACTIVE_CLIENT_BUF_SIZE);
	ipa3_active_clients_lock();
	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	cnt = ipa3_active_clients_log_print_buffer(active_clients_buf,
			IPA_DBG_ACTIVE_CLIENT_BUF_SIZE - IPA_MAX_MSG_LEN);
	table_size = ipa3_active_clients_log_print_table(active_clients_buf
			+ cnt, IPA_MAX_MSG_LEN);
	ipa3_active_clients_unlock();
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);

	return simple_read_from_buffer(ubuf, count, ppos,
			active_clients_buf, cnt + table_size);
+3 −6
Original line number Diff line number Diff line
@@ -850,9 +850,7 @@ struct ipa3_stats {

struct ipa3_active_clients {
	struct mutex mutex;
	spinlock_t spinlock;
	bool mutex_locked;
	int cnt;
	atomic_t cnt;
};

struct ipa3_wakelock_ref_cnt {
@@ -1851,6 +1849,8 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id);
int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info
		*id);
void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id);
void ipa3_dec_client_disable_clks_no_block(
	struct ipa_active_client_logging_info *id);
void ipa3_active_clients_log_dec(struct ipa_active_client_logging_info *id,
		bool int_ctx);
void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id,
@@ -1927,10 +1927,7 @@ int ipa3_resume_resource(enum ipa_rm_resource_name name);
bool ipa3_should_pipe_be_suspended(enum ipa_client_type client);
int ipa3_tag_aggr_force_close(int pipe_num);

void ipa3_active_clients_lock(void);
int ipa3_active_clients_trylock(unsigned long *flags);
void ipa3_active_clients_unlock(void);
void ipa3_active_clients_trylock_unlock(unsigned long *flags);
int ipa3_wdi_init(void);
int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id);
int ipa3_tag_process(struct ipa3_desc *desc, int num_descs,
+4 −10
Original line number Diff line number Diff line
@@ -322,27 +322,21 @@ static void ipa3_interrupt_defer(struct work_struct *work)

static irqreturn_t ipa3_isr(int irq, void *ctxt)
{
	unsigned long flags;
	struct ipa_active_client_logging_info log_info;

	IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info);
	IPADBG_LOW("Enter\n");
	/* defer interrupt handling in case IPA is not clocked on */
	if (ipa3_active_clients_trylock(&flags) == 0) {
	if (ipa3_inc_client_enable_clks_no_block(&log_info)) {
		IPADBG("defer interrupt processing\n");
		queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work);
		return IRQ_HANDLED;
	}

	if (ipa3_ctx->ipa3_active_clients.cnt == 0) {
		IPADBG("defer interrupt processing\n");
		queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work);
		goto bail;
	}

	ipa3_process_interrupts(true);
	IPADBG_LOW("Exit\n");

bail:
	ipa3_active_clients_trylock_unlock(&flags);
	ipa3_dec_client_disable_clks(&log_info);
	return IRQ_HANDLED;
}
/**
Loading