summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjay Chandrashekara <sanjayc@nvidia.com>2018-06-21 19:15:49 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-07-24 03:54:38 -0400
commit27c214726d8d5e76cece3deda271003090ad2c03 (patch)
tree274a9afe04d9edf793dbeb800fe2a970864a49a8
parente6210538bed3cde7ae968b1b2ba9fd0fc726ec3e (diff)
t19x: cpuidle: c6 exit latency measurement
Add support to measure C6 exit latency. This patch implements some of the helper functions required for this functionality. Measurement technique 1. Force cores 1 to 7 to enter C6 state. 2. Send an IPI from core 0 to wake all other cores 3. Measure exit latency based on trace printks 4. Check C6 entry count before and after "wfi" to make sure C6 was entered. JIRA: TPM-1217 Change-Id: I1d9943b09cf880631ad17f915bbf84959b899d2f Signed-off-by: Sanjay Chandrashekara <sanjayc@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1757458 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/cpuidle/cpuidle-tegra19x.c61
-rw-r--r--include/linux/platform/tegra/t19x-cpuidle.h8
2 files changed, 66 insertions, 3 deletions
diff --git a/drivers/cpuidle/cpuidle-tegra19x.c b/drivers/cpuidle/cpuidle-tegra19x.c
index 58ad5ac05..2166abbb7 100644
--- a/drivers/cpuidle/cpuidle-tegra19x.c
+++ b/drivers/cpuidle/cpuidle-tegra19x.c
@@ -34,6 +34,8 @@
34#include <linux/psci.h> 34#include <linux/psci.h>
35#include <linux/version.h> 35#include <linux/version.h>
36#include <linux/cpuhotplug.h> 36#include <linux/cpuhotplug.h>
37#include <linux/atomic.h>
38#include <linux/platform/tegra/t19x-cpuidle.h>
37 39
38#include <linux/of_gpio.h> 40#include <linux/of_gpio.h>
39#include <asm/cpuidle.h> 41#include <asm/cpuidle.h>
@@ -49,12 +51,15 @@
49#define CORE_WAKE_MASK 0x180C 51#define CORE_WAKE_MASK 0x180C
50#define T19x_CPUIDLE_C7_STATE 2 52#define T19x_CPUIDLE_C7_STATE 2
51#define T19x_CPUIDLE_C6_STATE 1 53#define T19x_CPUIDLE_C6_STATE 1
54#define MCE_STAT_ID_SHIFT 16UL
52 55
53static u32 read_cluster_info(struct device_node *of_states); 56static u32 read_cluster_info(struct device_node *of_states);
54static u32 deepest_cc_state; 57static u32 deepest_cc_state;
55static u32 deepest_cg_state; 58static u32 deepest_cg_state;
56static u64 forced_idle_state; 59static u64 forced_idle_state;
57static u64 forced_cluster_idle_state; 60static u64 forced_cluster_idle_state;
61static u64 test_c6_exit_latency;
62atomic_t entered_c6_cpu_count = ATOMIC_INIT(0);
58static u32 testmode; 63static u32 testmode;
59static struct cpuidle_driver t19x_cpu_idle_driver; 64static struct cpuidle_driver t19x_cpu_idle_driver;
60static int crossover_init(void); 65static int crossover_init(void);
@@ -88,11 +93,45 @@ static bool check_mce_version(void)
88 return false; 93 return false;
89} 94}
90 95
96int read_cpu_counter(void)
97{
98 return atomic_read(&entered_c6_cpu_count);
99}
100EXPORT_SYMBOL(read_cpu_counter);
101
102void clear_cpu_counter(void)
103{
104 atomic_set(&entered_c6_cpu_count, 0);
105}
106EXPORT_SYMBOL(clear_cpu_counter);
107
91static void t19x_cpu_enter_c6(u32 wake_time) 108static void t19x_cpu_enter_c6(u32 wake_time)
92{ 109{
93 arm_cpuidle_suspend(T19x_CPUIDLE_C6_STATE); 110 arm_cpuidle_suspend(T19x_CPUIDLE_C6_STATE);
94} 111}
95 112
113/*enter C6 function used in measuring C6 latency*/
114static void test_t19x_cpu_enter_c6(u32 wake_time)
115{
116 int cpu;
117 u64 val;
118 u32 mce_index;
119
120 cpu = smp_processor_id();
121 mce_index = (NVG_STAT_QUERY_C6_ENTRIES << MCE_STAT_ID_SHIFT)
122 + (u32)cpu;
123 tegra_mce_read_cstate_stats(mce_index, &val);
124 trace_printk("cpu = %d C6_COUNT_BEFORE = %llu\n", cpu, val);
125
126 atomic_inc(&entered_c6_cpu_count);
127
128 t19x_cpu_enter_c6(0);
129
130 trace_printk("Exiting C6\n");
131 tegra_mce_read_cstate_stats(mce_index, &val);
132 trace_printk("cpu = %d C6_COUNT_AFTER = %llu\n", cpu, val);
133}
134
96static void t19x_cpu_enter_c7(u32 wake_time) 135static void t19x_cpu_enter_c7(u32 wake_time)
97{ 136{
98 cpu_pm_enter(); /* power down notifier */ 137 cpu_pm_enter(); /* power down notifier */
@@ -147,7 +186,7 @@ static u32 t19x_make_power_state(u32 state)
147 t = ktime_to_timespec(tick_nohz_get_sleep_length()); 186 t = ktime_to_timespec(tick_nohz_get_sleep_length());
148 wake_time = t.tv_sec * tsc_per_sec + t.tv_nsec / nsec_per_tsc_tick; 187 wake_time = t.tv_sec * tsc_per_sec + t.tv_nsec / nsec_per_tsc_tick;
149 188
150 if (testmode) 189 if (testmode || test_c6_exit_latency)
151 wake_time = 0xFFFFEEEE; 190 wake_time = 0xFFFFEEEE;
152 191
153 /* The 8-LSB bits of wake time is lost and only 24 MSB bits 192 /* The 8-LSB bits of wake time is lost and only 24 MSB bits
@@ -267,8 +306,12 @@ static int forced_idle_write(void *data, u64 val)
267 306
268 if (pmstate == T19x_CPUIDLE_C7_STATE) 307 if (pmstate == T19x_CPUIDLE_C7_STATE)
269 t19x_cpu_enter_c7(wake_time); 308 t19x_cpu_enter_c7(wake_time);
270 else if (pmstate == T19x_CPUIDLE_C6_STATE) 309 else if (pmstate == T19x_CPUIDLE_C6_STATE) {
271 t19x_cpu_enter_c6(wake_time); 310 if (test_c6_exit_latency)
311 test_t19x_cpu_enter_c6(wake_time);
312 else
313 t19x_cpu_enter_c6(wake_time);
314 }
272 else 315 else
273 asm volatile("wfi\n"); 316 asm volatile("wfi\n");
274 317
@@ -293,6 +336,12 @@ static int forced_idle_write(void *data, u64 val)
293 return 0; 336 return 0;
294} 337}
295 338
339void force_idle_c6(u64 delay)
340{
341 forced_idle_write(NULL, delay);
342}
343EXPORT_SYMBOL(force_idle_c6);
344
296struct xover_smp_call_data { 345struct xover_smp_call_data {
297 int index; 346 int index;
298 int value; 347 int value;
@@ -407,6 +456,12 @@ static int cpuidle_debugfs_init(void)
407 if (!dfs_file) 456 if (!dfs_file)
408 goto err_out; 457 goto err_out;
409 458
459 dfs_file = debugfs_create_u64("test_c6_exit_latency", 0644,
460 cpuidle_debugfs_node, &test_c6_exit_latency);
461
462 if (!dfs_file)
463 goto err_out;
464
410 dfs_file = debugfs_create_u64("forced_cluster_idle_state", 0644, 465 dfs_file = debugfs_create_u64("forced_cluster_idle_state", 0644,
411 cpuidle_debugfs_node, &forced_cluster_idle_state); 466 cpuidle_debugfs_node, &forced_cluster_idle_state);
412 467
diff --git a/include/linux/platform/tegra/t19x-cpuidle.h b/include/linux/platform/tegra/t19x-cpuidle.h
new file mode 100644
index 000000000..5c9275d78
--- /dev/null
+++ b/include/linux/platform/tegra/t19x-cpuidle.h
@@ -0,0 +1,8 @@
1#ifndef __T19x_CPUIDLE_C6_LATENCY__
2#define __T19x_CPUIDLE_C6_LATENCY__
3
4void force_idle_c6(u64 delay);
5int read_cpu_counter(void);
6void clear_cpu_counter(void);
7#endif
8