diff options
-rw-r--r-- | drivers/misc/tegra-profiler/power_clk.c | 110 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/version.h | 2 | ||||
-rw-r--r-- | include/linux/tegra_profiler.h | 15 |
3 files changed, 108 insertions, 19 deletions
diff --git a/drivers/misc/tegra-profiler/power_clk.c b/drivers/misc/tegra-profiler/power_clk.c index b7b198333fae..cf72b46126ba 100644 --- a/drivers/misc/tegra-profiler/power_clk.c +++ b/drivers/misc/tegra-profiler/power_clk.c @@ -32,24 +32,32 @@ #include "comm.h" #include "debug.h" -#define POWER_CLK_MAX_VALUES 32 - -typedef int (*notifier_call_ft)(struct notifier_block *, - unsigned long, void *); +#define PCLK_MAX_VALUES 32 struct power_clk_data { unsigned long value; unsigned long prev; }; +#define PCLK_NB_GPU 0 +#define PCLK_NB_EMC 0 + +enum { + PCLK_NB_CPU_FREQ, + PCLK_NB_CPU_HOTPLUG, + PCLK_NB_CPU_MAX, +}; + +#define PCLK_NB_MAX PCLK_NB_CPU_MAX + struct power_clk_source { int type; struct clk *clkp; - struct notifier_block nb; + struct notifier_block nb[PCLK_NB_MAX]; int nr; - struct power_clk_data data[POWER_CLK_MAX_VALUES]; + struct power_clk_data data[PCLK_MAX_VALUES]; atomic_t active; struct mutex lock; @@ -127,6 +135,22 @@ static void make_sample(void) quadd_put_sample(&record, &vec, 1); } +static void +make_sample_hotplug(int cpu, int is_online) +{ + struct quadd_record_data record; + struct quadd_hotplug_data *s = &record.hotplug; + + record.record_type = QUADD_RECORD_TYPE_HOTPLUG; + + s->cpu = cpu; + s->is_online = is_online ? 1 : 0; + s->time = quadd_get_time(); + s->reserved = 0; + + quadd_put_sample(&record, NULL, 0); +} + static inline int is_data_changed(struct power_clk_source *s) { @@ -326,6 +350,48 @@ cpufreq_notifier_call(struct notifier_block *nb, return 0; } +static int +cpu_hotplug_notifier_call(struct notifier_block *nb, + unsigned long action, void *hcpu) +{ + int cpu; + struct power_clk_source *s = &power_ctx.cpu; + + if (!atomic_read(&s->active)) + return NOTIFY_DONE; + + cpu = (long)hcpu; + + pr_debug("cpu: %d, action: %lu\n", cpu, action); + + if (cpu >= s->nr) { + pr_err_once("error: cpu id: %d\n", cpu); + return NOTIFY_DONE; + } + + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + make_sample_hotplug(cpu, 1); + break; + + case CPU_DEAD: + case CPU_DEAD_FROZEN: + mutex_lock(&s->lock); + if (atomic_read(&s->active)) + s->data[cpu].value = 0; + mutex_unlock(&s->lock); + + make_sample_hotplug(cpu, 0); + break; + + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + static void reset_data(struct power_clk_source *s) { int i; @@ -339,13 +405,11 @@ static void reset_data(struct power_clk_source *s) } static void init_source(struct power_clk_source *s, - notifier_call_ft notifier, int nr_values, int type) { s->type = type; - s->nb.notifier_call = notifier; - s->nr = min_t(int, nr_values, POWER_CLK_MAX_VALUES); + s->nr = min_t(int, nr_values, PCLK_MAX_VALUES); atomic_set(&s->active, 0); mutex_init(&s->lock); @@ -508,23 +572,37 @@ void quadd_power_clk_stop(void) int quadd_power_clk_init(struct quadd_ctx *quadd_ctx) { - init_source(&power_ctx.cpu, cpufreq_notifier_call, nr_cpu_ids, - QUADD_POWER_CLK_CPU); + struct power_clk_source *s; - init_source(&power_ctx.gpu, gpu_notifier_call, 1, QUADD_POWER_CLK_GPU); - init_source(&power_ctx.emc, emc_notifier_call, 1, QUADD_POWER_CLK_EMC); + s = &power_ctx.gpu; + s->nb[PCLK_NB_GPU].notifier_call = gpu_notifier_call; + init_source(s, 1, QUADD_POWER_CLK_GPU); - cpufreq_register_notifier(&power_ctx.cpu.nb, - CPUFREQ_TRANSITION_NOTIFIER); + s = &power_ctx.emc; + s->nb[PCLK_NB_EMC].notifier_call = emc_notifier_call; + init_source(s, 1, QUADD_POWER_CLK_EMC); + + s = &power_ctx.cpu; + s->nb[PCLK_NB_CPU_FREQ].notifier_call = cpufreq_notifier_call; + s->nb[PCLK_NB_CPU_HOTPLUG].notifier_call = cpu_hotplug_notifier_call; + init_source(s, nr_cpu_ids, QUADD_POWER_CLK_CPU); power_ctx.quadd_ctx = quadd_ctx; + cpufreq_register_notifier(&s->nb[PCLK_NB_CPU_FREQ], + CPUFREQ_TRANSITION_NOTIFIER); + register_cpu_notifier(&s->nb[PCLK_NB_CPU_HOTPLUG]); + return 0; } void quadd_power_clk_deinit(void) { + struct power_clk_source *s = &power_ctx.cpu; + quadd_power_clk_stop(); - cpufreq_unregister_notifier(&power_ctx.cpu.nb, + + cpufreq_unregister_notifier(&s->nb[PCLK_NB_CPU_FREQ], CPUFREQ_TRANSITION_NOTIFIER); + unregister_cpu_notifier(&s->nb[PCLK_NB_CPU_HOTPLUG]); } diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h index 7fdf4c4bfadf..30da60f3f069 100644 --- a/drivers/misc/tegra-profiler/version.h +++ b/drivers/misc/tegra-profiler/version.h @@ -18,7 +18,7 @@ #ifndef __QUADD_VERSION_H #define __QUADD_VERSION_H -#define QUADD_MODULE_VERSION "1.102" +#define QUADD_MODULE_VERSION "1.103" #define QUADD_MODULE_BRANCH "Dev" #endif /* __QUADD_VERSION_H */ diff --git a/include/linux/tegra_profiler.h b/include/linux/tegra_profiler.h index 3462998f9872..caf58e63ed70 100644 --- a/include/linux/tegra_profiler.h +++ b/include/linux/tegra_profiler.h @@ -1,7 +1,7 @@ /* * include/linux/tegra_profiler.h * - * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,7 +19,7 @@ #include <linux/ioctl.h> -#define QUADD_SAMPLES_VERSION 33 +#define QUADD_SAMPLES_VERSION 34 #define QUADD_IO_VERSION 18 #define QUADD_IO_VERSION_DYNAMIC_RB 5 @@ -52,6 +52,7 @@ #define QUADD_SAMPLE_VERSION_STACK_OFFSET 31 #define QUADD_SAMPLE_VERSION_SCHED_TASK_STATE 32 #define QUADD_SAMPLE_VERSION_URCS 33 +#define QUADD_SAMPLE_VERSION_HOTPLUG 34 #define QUADD_MMAP_HEADER_VERSION 1 @@ -152,6 +153,7 @@ enum quadd_record_type { QUADD_RECORD_TYPE_POWER_RATE, QUADD_RECORD_TYPE_ADDITIONAL_SAMPLE, QUADD_RECORD_TYPE_SCHED, + QUADD_RECORD_TYPE_HOTPLUG, }; enum quadd_event_source { @@ -258,6 +260,14 @@ struct quadd_power_rate_data { u32 emc; }; +struct quadd_hotplug_data { + u64 time; + u32 cpu; + + u32 is_online:1, + reserved:31; +}; + struct quadd_additional_sample { u8 type; @@ -353,6 +363,7 @@ struct quadd_record_data { struct quadd_debug_data debug; struct quadd_header_data hdr; struct quadd_power_rate_data power_rate; + struct quadd_hotplug_data hotplug; struct quadd_sched_data sched; struct quadd_additional_sample additional_sample; }; |