summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorIgor Nabirushkin <inabirushkin@nvidia.com>2015-04-29 10:44:01 +0400
committerWinnie Hsu <whsu@nvidia.com>2015-05-29 14:29:28 -0700
commit120e8796ffbdcaa979a22de71b2036a64d924b08 (patch)
tree9658a030c864b36836fd78762117f47146dc2662 /drivers/misc
parent41e526efda84af5850e664dc5bfbe4eedbc1435e (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.c110
-rw-r--r--drivers/misc/tegra-profiler/version.h2
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 */