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

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

Merge "lpm-stats: Optimize stats path"

parents 6c0636bb 03ccdeb0
Loading
Loading
Loading
Loading
+32 −15
Original line number Diff line number Diff line
@@ -92,9 +92,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb,
				unsigned long action, void *hcpu);

static void cluster_unprepare(struct lpm_cluster *cluster,
		const struct cpumask *cpu, int child_idx, bool from_idle);
		const struct cpumask *cpu, int child_idx, bool from_idle,
		int64_t time);
static void cluster_prepare(struct lpm_cluster *cluster,
		const struct cpumask *cpu, int child_idx, bool from_idle);
		const struct cpumask *cpu, int child_idx, bool from_idle,
		int64_t time);

static struct notifier_block __refdata lpm_cpu_nblk = {
	.notifier_call = lpm_cpu_callback,
@@ -184,11 +186,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb,
	switch (action & ~CPU_TASKS_FROZEN) {
	case CPU_DYING:
		cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu),
					NR_LPM_LEVELS, false);
					NR_LPM_LEVELS, false, 0);
		break;
	case CPU_STARTING:
		cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu),
					NR_LPM_LEVELS, false);
					NR_LPM_LEVELS, false, 0);
		break;
	case CPU_ONLINE:
		smp_call_function_single(cpu, setup_broadcast_timer,
@@ -575,7 +577,8 @@ failed_set_mode:
}

static void cluster_prepare(struct lpm_cluster *cluster,
		const struct cpumask *cpu, int child_idx, bool from_idle)
		const struct cpumask *cpu, int child_idx, bool from_idle,
		int64_t start_time)
{
	int i;

@@ -616,15 +619,21 @@ static void cluster_prepare(struct lpm_cluster *cluster,
	if (cluster_configure(cluster, i, from_idle))
		goto failed;

	cluster->stats->sleep_time = start_time;
	cluster_prepare(cluster->parent, &cluster->num_children_in_sync, i,
			from_idle);
			from_idle, start_time);

	spin_unlock(&cluster->sync_lock);
	return;
failed:
	spin_unlock(&cluster->sync_lock);
	cluster->stats->sleep_time = 0;
	return;
}

static void cluster_unprepare(struct lpm_cluster *cluster,
		const struct cpumask *cpu, int child_idx, bool from_idle)
		const struct cpumask *cpu, int child_idx, bool from_idle,
		int64_t end_time)
{
	struct lpm_cluster_level *level;
	bool first_cpu;
@@ -654,6 +663,9 @@ static void cluster_unprepare(struct lpm_cluster *cluster,
	if (!first_cpu || cluster->last_level == cluster->default_level)
		goto unlock_return;

	if (cluster->stats->sleep_time)
		cluster->stats->sleep_time = end_time -
			cluster->stats->sleep_time;
	lpm_stats_cluster_exit(cluster->stats, cluster->last_level, true);

	level = &cluster->levels[cluster->last_level];
@@ -690,7 +702,7 @@ static void cluster_unprepare(struct lpm_cluster *cluster,

	cluster_notify(cluster, &cluster->levels[last_level], false);
	cluster_unprepare(cluster->parent, &cluster->child_cpus,
			last_level, from_idle);
			last_level, from_idle, end_time);
unlock_return:
	spin_unlock(&cluster->sync_lock);
}
@@ -875,13 +887,13 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev,
		pwr_params->energy_overhead, pwr_params->latency_us);

	cpu_prepare(cluster, idx, true);
	cluster_prepare(cluster, cpumask, idx, true);
	cluster_prepare(cluster, cpumask, idx, true, ktime_to_ns(ktime_get()));

	if (need_resched() || (idx < 0))
		goto exit;

	trace_cpu_idle_enter(idx);
	lpm_stats_cpu_enter(idx);
	lpm_stats_cpu_enter(idx, start_time);

	if (!use_psci) {
		if (idx > 0)
@@ -898,8 +910,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev,
	}

exit:
	lpm_stats_cpu_exit(idx, success);
	cluster_unprepare(cluster, cpumask, idx, true);
	end_time = ktime_to_ns(ktime_get());
	lpm_stats_cpu_exit(idx, end_time, success);

	cluster_unprepare(cluster, cpumask, idx, true, end_time);
	cpu_unprepare(cluster, idx, true);

	sched_set_cpu_cstate(smp_processor_id(), 0, 0, 0);
@@ -1111,6 +1125,7 @@ static int lpm_suspend_enter(suspend_state_t state)
	struct lpm_cpu *lpm_cpu = cluster->cpu;
	const struct cpumask *cpumask = get_cpu_mask(cpu);
	int idx;
	int64_t time = ktime_to_ns(ktime_get());

	for (idx = lpm_cpu->nlevels - 1; idx >= 0; idx--) {

@@ -1122,7 +1137,7 @@ static int lpm_suspend_enter(suspend_state_t state)
		return 0;
	}
	cpu_prepare(cluster, idx, false);
	cluster_prepare(cluster, cpumask, idx, false);
	cluster_prepare(cluster, cpumask, idx, false, time);
	if (idx > 0)
		update_debug_pc_event(CPU_ENTER, idx, 0xdeaffeed,
					0xdeaffeed, false);
@@ -1143,7 +1158,9 @@ static int lpm_suspend_enter(suspend_state_t state)
	if (idx > 0)
		update_debug_pc_event(CPU_EXIT, idx, true, 0xdeaffeed,
					false);
	cluster_unprepare(cluster, cpumask, idx, false);

	time = ktime_to_ns(ktime_get());
	cluster_unprepare(cluster, cpumask, idx, false, time);
	cpu_unprepare(cluster, idx, false);
	return 0;
}
@@ -1354,7 +1371,7 @@ void lpm_cpu_hotplug_enter(unsigned int cpu)
			return;

		BUG_ON(idx < 0);
		cluster_prepare(cluster, get_cpu_mask(cpu), idx, false);
		cluster_prepare(cluster, get_cpu_mask(cpu), idx, false, 0);
	}

	msm_cpu_pm_enter_sleep(mode, false);
+10 −30
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 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
@@ -24,6 +24,7 @@
#include <linux/suspend.h>
#include <soc/qcom/spm.h>
#include <soc/qcom/pm.h>
#include <soc/qcom/lpm-stats.h>

#define MAX_STR_LEN 256
const char *lpm_stats_reset = "reset";
@@ -42,24 +43,6 @@ struct level_stats {
	uint64_t enter_time;
};

struct lifo_stats {
	uint32_t last_in;
	uint32_t first_out;
};

struct lpm_stats {
	char name[MAX_STR_LEN];
	struct level_stats *time_stats;
	uint32_t num_levels;
	struct lifo_stats lifo;
	struct lpm_stats *parent;
	struct list_head sibling;
	struct list_head child;
	struct cpumask mask;
	struct dentry *directory;
	bool is_cpu;
};

static struct level_stats suspend_time_stats;

static DEFINE_PER_CPU_SHARED_ALIGNED(struct lpm_stats, cpu_stats);
@@ -425,13 +408,9 @@ static inline void update_exit_stats(struct lpm_stats *stats, uint32_t index,
	uint64_t exit_time = 0;

	/* Update time stats only when exit is preceded by enter */
	if (stats->time_stats[index].enter_time) {
		exit_time = sched_clock() -
				stats->time_stats[index].enter_time;
	exit_time = stats->sleep_time;
	update_level_stats(&stats->time_stats[index], exit_time,
					success);
		stats->time_stats[index].enter_time = 0;
	}
}

static int config_level(const char *name, const char **levels,
@@ -679,8 +658,6 @@ void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index)
	if (IS_ERR_OR_NULL(stats))
		return;

	stats->time_stats[index].enter_time = sched_clock();

	update_last_in_stats(stats);
}
EXPORT_SYMBOL(lpm_stats_cluster_enter);
@@ -717,14 +694,15 @@ EXPORT_SYMBOL(lpm_stats_cluster_exit);
 * Function to communicate the low power mode level that the cpu is
 * prepared to enter.
 */
void lpm_stats_cpu_enter(uint32_t index)
void lpm_stats_cpu_enter(uint32_t index, uint64_t time)
{
	struct lpm_stats *stats = &__get_cpu_var(cpu_stats);

	stats->sleep_time = time;

	if (!stats->time_stats)
		return;

	stats->time_stats[index].enter_time = sched_clock();
}
EXPORT_SYMBOL(lpm_stats_cpu_enter);

@@ -736,13 +714,15 @@ EXPORT_SYMBOL(lpm_stats_cpu_enter);
 *
 * Function to communicate the low power mode level that the cpu exited.
 */
void lpm_stats_cpu_exit(uint32_t index, bool success)
void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success)
{
	struct lpm_stats *stats = &__get_cpu_var(cpu_stats);

	if (!stats->time_stats)
		return;

	stats->sleep_time = time - stats->sleep_time;

	update_exit_stats(stats, index, success);
}
EXPORT_SYMBOL(lpm_stats_cpu_exit);
+29 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015, 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
@@ -17,6 +17,29 @@

struct lpm_stats;

#define MAX_STR_LEN 256

struct lifo_stats {
	uint32_t last_in;
	uint32_t first_out;
};

struct lpm_stats {
	char name[MAX_STR_LEN];
	struct level_stats *time_stats;
	uint32_t num_levels;
	struct lifo_stats lifo;
	struct lpm_stats *parent;
	struct list_head sibling;
	struct list_head child;
	struct cpumask mask;
	struct dentry *directory;
	int64_t sleep_time;
	bool is_cpu;
};



#ifdef CONFIG_MSM_IDLE_STATS
struct lpm_stats *lpm_stats_config_level(const char *name,
	const char **levels, int num_levels, struct lpm_stats *parent,
@@ -24,8 +47,8 @@ struct lpm_stats *lpm_stats_config_level(const char *name,
void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index);
void lpm_stats_cluster_exit(struct lpm_stats *stats, uint32_t index,
				bool success);
void lpm_stats_cpu_enter(uint32_t index);
void lpm_stats_cpu_exit(uint32_t index, bool success);
void lpm_stats_cpu_enter(uint32_t index, uint64_t time);
void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success);
void lpm_stats_suspend_enter(void);
void lpm_stats_suspend_exit(void);
#else
@@ -48,12 +71,13 @@ static inline void lpm_stats_cluster_exit(struct lpm_stats *stats,
	return;
}

static inline void lpm_stats_cpu_enter(uint32_t index)
static inline void lpm_stats_cpu_enter(uint32_t index, uint64_t time)
{
	return;
}

static inline void lpm_stats_cpu_exit(uint32_t index, bool success)
static inline void lpm_stats_cpu_exit(uint32_t index, bool success,
							uint64_t time)
{
	return;
}