[linux-yocto] [PATCH 11/12] MIPS: Add support for OCTEON III perf events.
Chandrakala Chavva
cchavva.cavm at gmail.com
Thu Jan 29 07:32:10 PST 2015
From: Abhishek Paliwal <abhishek.paliwal at aricent.com>
From: David Daney <david.daney at cavium.com>
They are mostly the same as previous OCTEON models, but we need to
enable them for the OCTEON III CPUs.
Signed-off-by: David Daney <david.daney at cavium.com>
Signed-off-by: Abhishek Paliwal <abhishek.paliwal at aricent.com>
---
arch/mips/cavium-octeon/setup.c | 38 ++++++++++++++++++++++++++++++++++++
arch/mips/include/asm/perf_event.h | 10 +++++++++-
arch/mips/kernel/perf_event_mipsxx.c | 35 +++++++++++++++++++++++++--------
3 files changed, 74 insertions(+), 9 deletions(-)
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index eb67381..2b152c1 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -37,6 +37,7 @@
#include <asm/bootinfo.h>
#include <asm/sections.h>
#include <asm/time.h>
+#include <asm/perf_event.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/pci-octeon.h>
@@ -926,6 +927,43 @@ void __init prom_init(void)
octeon_setup_smp();
}
+#ifdef CONFIG_HW_PERF_EVENTS
+static int octeon_mipspmu_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ u64 cvmctl_orig = read_c0_cvmctl();
+ u64 cvmctl_new = cvmctl_orig;
+ u64 mask = (1ull << 15) | (1ull << 17);
+
+ switch (action) {
+ case MIPSPMU_ACTIVE:
+ cvmctl_new = cvmctl_orig | mask;
+ /*
+ * Set CvmCtl[DCICLK,DISCE] for more accurate profiling at
+ * the expense of power consumption.
+ */
+ break;
+ case MIPSPMU_INACTIVE:
+ cvmctl_new = cvmctl_orig & ~mask;
+ break;
+ default:
+ break;
+ }
+ if (cvmctl_new != cvmctl_orig)
+ write_c0_cvmctl(cvmctl_new);
+ return NOTIFY_OK;
+}
+static struct notifier_block octeon_mipspmu_nb = {
+ .notifier_call = octeon_mipspmu_notifier
+};
+
+static int __init octeon_setup_mipspmu_notifiers(void)
+{
+ return mipspmu_notifier_register(&octeon_mipspmu_nb);
+}
+late_initcall(octeon_setup_mipspmu_notifiers);
+#endif
+
/* Exclude a single page from the regions obtained in plat_mem_setup. */
#ifndef CONFIG_CRASH_DUMP
static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
diff --git a/arch/mips/include/asm/perf_event.h b/arch/mips/include/asm/perf_event.h
index d0c7749..bfd8f0a 100644
--- a/arch/mips/include/asm/perf_event.h
+++ b/arch/mips/include/asm/perf_event.h
@@ -11,5 +11,13 @@
#ifndef __MIPS_PERF_EVENT_H__
#define __MIPS_PERF_EVENT_H__
-/* Leave it empty here. The file is required by linux/perf_event.h */
+
+#include <linux/notifier.h>
+
+/* Allow CPU specific actions on PMU state changes. */
+int mipspmu_notifier_register(struct notifier_block *nb);
+int mipspmu_notifier_unregister(struct notifier_block *nb);
+#define MIPSPMU_ACTIVE 0
+#define MIPSPMU_INACTIVE 1
+
#endif /* __MIPS_PERF_EVENT_H__ */
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 24cdf64..3aae869 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -77,6 +77,17 @@ struct mips_perf_event {
#endif
};
+static ATOMIC_NOTIFIER_HEAD(mipsxx_pmu_chain);
+int mipspmu_notifier_register(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&mipsxx_pmu_chain, nb);
+}
+
+int mipspmu_notifier_unregister(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&mipsxx_pmu_chain, nb);
+}
+
static struct mips_perf_event raw_event;
static DEFINE_MUTEX(raw_event_mutex);
@@ -175,7 +186,7 @@ static unsigned int counters_total_to_per_cpu(unsigned int counters)
#endif /* CONFIG_MIPS_PERF_SHARED_TC_COUNTERS */
-static void resume_local_counters(void);
+static int resume_local_counters(void);
static void pause_local_counters(void);
static irqreturn_t mipsxx_pmu_handle_irq(int, void *);
static int mipsxx_pmu_handle_shared_irq(void);
@@ -522,10 +533,12 @@ static void mipspmu_read(struct perf_event *event)
static void mipspmu_enable(struct pmu *pmu)
{
+ int i;
#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
write_unlock(&pmuint_rwlock);
#endif
- resume_local_counters();
+ i = resume_local_counters();
+ atomic_notifier_call_chain(&mipsxx_pmu_chain, i ? MIPSPMU_ACTIVE : MIPSPMU_INACTIVE, NULL);
}
/*
@@ -803,6 +816,7 @@ static void reset_counters(void *arg)
mipsxx_pmu_write_control(0, 0);
mipspmu.write_counter(0, 0);
}
+ atomic_notifier_call_chain(&mipsxx_pmu_chain, MIPSPMU_INACTIVE, NULL);
}
/* 24K/34K/1004K cores can share the same event map. */
@@ -1284,15 +1298,19 @@ static void pause_local_counters(void)
local_irq_restore(flags);
}
-static void resume_local_counters(void)
+static int resume_local_counters(void)
{
+ int r = 0;
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int ctr = mipspmu.num_counters;
do {
ctr--;
mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr]);
+ r += (cpuc->saved_ctrl[ctr] & M_PERFCTL_INTERRUPT_ENABLE) != 0;
} while (ctr > 0);
+
+ return r;
}
static int mipsxx_pmu_handle_shared_irq(void)
@@ -1479,14 +1497,15 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
{
- unsigned int raw_id = config & 0xff;
- unsigned int base_id = raw_id & 0x7f;
-
+ unsigned int base_id = config & 0x7f;
raw_event.cntr_mask = CNTR_ALL;
raw_event.event_id = base_id;
- if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
+ if (current_cpu_type() == CPU_CAVIUM_OCTEON3) {
+ if (base_id > 0x5f)
+ return ERR_PTR(-EOPNOTSUPP);
+ } else if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
if (base_id > 0x42)
return ERR_PTR(-EOPNOTSUPP);
} else {
@@ -1501,7 +1520,6 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
case 0x1f:
case 0x2f:
case 0x34:
- case 0x3b ... 0x3f:
return ERR_PTR(-EOPNOTSUPP);
default:
break;
@@ -1592,6 +1610,7 @@ init_hw_perf_events(void)
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
+ case CPU_CAVIUM_OCTEON3:
mipspmu.name = "octeon";
mipspmu.general_event_map = &octeon_event_map;
mipspmu.cache_event_map = &octeon_cache_map;
--
1.8.1.4
More information about the linux-yocto
mailing list