diff options
author | Igor Nabirushkin <inabirushkin@nvidia.com> | 2015-04-29 10:44:01 +0400 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2015-05-29 14:29:28 -0700 |
commit | 120e8796ffbdcaa979a22de71b2036a64d924b08 (patch) | |
tree | 9658a030c864b36836fd78762117f47146dc2662 /drivers/misc | |
parent | 41e526efda84af5850e664dc5bfbe4eedbc1435e (diff) |
misc: tegra-profiler: add cpu notifier
Detect when the CPU goes online/offline.
Bug 1634024
Change-Id: I989a9aefbc32a70070b37fe42ce5dcf75b18263b
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/729497
(cherry picked from commit a2eec5a5ea12fb50e073b322ca9d948818179968)
Reviewed-on: http://git-master/r/748094
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Andrey Trachenko <atrachenko@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/tegra-profiler/power_clk.c | 110 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/version.h | 2 |
2 files changed, 95 insertions, 17 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 */ |