All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] ARM perf updates for 3.7
@ 2012-08-10 17:36 Will Deacon
  2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
                   ` (9 more replies)
  0 siblings, 10 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

This patch series contains the ARM perf updates I'd like to push for 3.7
Most of the code is cleanup in preparation for big.LITTLE PMU support,
where we will need to support different types of CPU PMU on the same SoC.

The PMU probing has changed so that we try to identify the PMU using its
DT binding before falling back to probing the current core. The unused
PMU registration mechanism is also removed and platforms registering
the device have been updated accordingly.

Given that this touches a few platforms, I anticipate sending it via
arm-soc.

All feedback welcome,

Will


Jon Hunter (1):
  ARM: PMU: Add runtime PM Support

Sudeep KarkadaNagesha (2):
  ARM: pmu: remove arm_pmu_type enumeration
  ARM: perf: move irq registration into pmu implementation

Will Deacon (6):
  ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs
  ARM: pmu: remove unused reservation mechanism
  ARM: perf: remove mysterious compiler barrier
  ARM: perf: probe devicetree in preference to current CPU
  ARM: perf: prepare for moving CPU PMU code into separate file
  ARM: perf: move CPU-specific PMU handling code into separate file

 Documentation/devicetree/bindings/arm/pmu.txt |    4 +
 MAINTAINERS                                   |    1 -
 arch/arm/Kconfig                              |    8 +-
 arch/arm/include/asm/perf_event.h             |    9 +-
 arch/arm/include/asm/pmu.h                    |   77 ++----
 arch/arm/kernel/Makefile                      |    3 +-
 arch/arm/kernel/perf_event.c                  |  347 ++++---------------------
 arch/arm/kernel/perf_event_cpu.c              |  295 +++++++++++++++++++++
 arch/arm/kernel/perf_event_v6.c               |   12 +-
 arch/arm/kernel/perf_event_v7.c               |   32 ++--
 arch/arm/kernel/perf_event_xscale.c           |   10 +-
 arch/arm/kernel/pmu.c                         |   36 ---
 arch/arm/mach-bcmring/arch.c                  |    3 +-
 arch/arm/mach-omap2/devices.c                 |    3 +-
 arch/arm/mach-pxa/devices.c                   |    3 +-
 arch/arm/mach-realview/realview_eb.c          |    3 +-
 arch/arm/mach-realview/realview_pb1176.c      |    3 +-
 arch/arm/mach-realview/realview_pb11mp.c      |    3 +-
 arch/arm/mach-realview/realview_pba8.c        |    3 +-
 arch/arm/mach-realview/realview_pbx.c         |    3 +-
 arch/arm/mach-tegra/devices.c                 |    3 +-
 arch/arm/mach-ux500/cpu-db8500.c              |    3 +-
 arch/arm/mach-vexpress/ct-ca9x4.c             |    3 +-
 arch/arm/plat-iop/pmu.c                       |    3 +-
 arch/arm/plat-samsung/devs.c                  |    3 +-
 25 files changed, 424 insertions(+), 449 deletions(-)
 create mode 100644 arch/arm/kernel/perf_event_cpu.c
 delete mode 100644 arch/arm/kernel/pmu.c

-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/9] ARM: PMU: Add runtime PM Support
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-11 15:09   ` Ming Lei
  2012-08-10 17:36 ` [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs Will Deacon
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Hunter <jon-hunter@ti.com>

Add runtime PM support to the ARM PMU driver so that devices such as OMAP
supporting dynamic PM can use the platform->runtime_* hooks to initialise
hardware at runtime. Without having these runtime PM hooks in place any
configuration of the PMU hardware would be lost when low power states are
entered and hence would prevent PMU from working.

This change also replaces the PMU platform functions enable_irq and disable_irq
added by Ming Lei with runtime_resume and runtime_suspend funtions. Ming had
added the enable_irq and disable_irq functions as a method to configure the
cross trigger interface on OMAP4 for routing the PMU interrupts. By adding
runtime PM support, we can move the code called by enable_irq and disable_irq
into the runtime PM callbacks runtime_resume and runtime_suspend.

Cc: Ming Lei <ming.lei@canonical.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/include/asm/pmu.h   |   20 ++++++++++++--------
 arch/arm/kernel/perf_event.c |   41 +++++++++++++++++++++++++++++++++--------
 2 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 4432305..40d7dff 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -31,18 +31,22 @@ enum arm_pmu_type {
  *	interrupt and passed the address of the low level handler,
  *	and can be used to implement any platform specific handling
  *	before or after calling it.
- * @enable_irq: an optional handler which will be called after
- *	request_irq and be used to handle some platform specific
- *	irq enablement
- * @disable_irq: an optional handler which will be called before
- *	free_irq and be used to handle some platform specific
- *	irq disablement
+ * @runtime_resume: an optional handler which will be called by the
+ *	runtime PM framework following a call to pm_runtime_get().
+ *	Note that if pm_runtime_get() is called more than once in
+ *	succession this handler will only be called once.
+ * @runtime_suspend: an optional handler which will be called by the
+ *	runtime PM framework following a call to pm_runtime_put().
+ *	Note that if pm_runtime_get() is called more than once in
+ *	succession this handler will only be called following the
+ *	final call to pm_runtime_put() that actually disables the
+ *	hardware.
  */
 struct arm_pmu_platdata {
 	irqreturn_t (*handle_irq)(int irq, void *dev,
 				  irq_handler_t pmu_handler);
-	void (*enable_irq)(int irq);
-	void (*disable_irq)(int irq);
+	int (*runtime_resume)(struct device *dev);
+	int (*runtime_suspend)(struct device *dev);
 };
 
 #ifdef CONFIG_CPU_HAS_PMU
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index ab243b8..c44647e 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -364,8 +365,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
 {
 	int i, irq, irqs;
 	struct platform_device *pmu_device = armpmu->plat_device;
-	struct arm_pmu_platdata *plat =
-		dev_get_platdata(&pmu_device->dev);
 
 	irqs = min(pmu_device->num_resources, num_possible_cpus());
 
@@ -373,13 +372,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
 		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
 			continue;
 		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0) {
-			if (plat && plat->disable_irq)
-				plat->disable_irq(irq);
+		if (irq >= 0)
 			free_irq(irq, armpmu);
-		}
 	}
 
+	pm_runtime_put_sync(&pmu_device->dev);
 	release_pmu(armpmu->type);
 }
 
@@ -412,6 +409,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
 		return -ENODEV;
 	}
 
+	pm_runtime_get_sync(&pmu_device->dev);
+
 	for (i = 0; i < irqs; ++i) {
 		err = 0;
 		irq = platform_get_irq(pmu_device, i);
@@ -437,8 +436,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
 				irq);
 			armpmu_release_hardware(armpmu);
 			return err;
-		} else if (plat && plat->enable_irq)
-			plat->enable_irq(irq);
+		}
 
 		cpumask_set_cpu(i, &armpmu->active_irqs);
 	}
@@ -581,6 +579,28 @@ static void armpmu_disable(struct pmu *pmu)
 	armpmu->stop();
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int armpmu_runtime_resume(struct device *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+	if (plat && plat->runtime_resume)
+		return plat->runtime_resume(dev);
+
+	return 0;
+}
+
+static int armpmu_runtime_suspend(struct device *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+	if (plat && plat->runtime_suspend)
+		return plat->runtime_suspend(dev);
+
+	return 0;
+}
+#endif
+
 static void __init armpmu_init(struct arm_pmu *armpmu)
 {
 	atomic_set(&armpmu->active_events, 0);
@@ -647,9 +667,14 @@ static int __devinit armpmu_device_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct dev_pm_ops armpmu_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+};
+
 static struct platform_driver armpmu_driver = {
 	.driver		= {
 		.name	= "arm-pmu",
+		.pm	= &armpmu_dev_pm_ops,
 		.of_match_table = armpmu_of_device_ids,
 	},
 	.probe		= armpmu_device_probe,
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
  2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 18:42   ` Rob Herring
  2012-08-10 17:36 ` [PATCH 3/9] ARM: pmu: remove unused reservation mechanism Will Deacon
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds separate devicetree bindings for 11MPcore and
Cortex-{A5,A7,A15} PMUs in preparation for improved devicetree parsing
in the ARM perf-event CPU PMU driver.

Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 Documentation/devicetree/bindings/arm/pmu.txt |    4 ++++
 arch/arm/kernel/perf_event.c                  |    6 +++++-
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
index 1c044eb..343781b 100644
--- a/Documentation/devicetree/bindings/arm/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -7,8 +7,12 @@ representation in the device tree should be done as under:-
 Required properties:
 
 - compatible : should be one of
+	"arm,cortex-a15-pmu"
 	"arm,cortex-a9-pmu"
 	"arm,cortex-a8-pmu"
+	"arm,cortex-a7-pmu"
+	"arm,cortex-a5-pmu"
+	"arm,arm11mpcore-pmu"
 	"arm,arm1176-pmu"
 	"arm,arm1136-pmu"
 - interrupts : 1 combined interrupt or 1 per core.
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c44647e..3aa3388 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -646,10 +646,14 @@ arch_initcall(cpu_pmu_reset);
  * PMU platform driver and devicetree bindings.
  */
 static struct of_device_id armpmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a15-pmu"},
 	{.compatible = "arm,cortex-a9-pmu"},
 	{.compatible = "arm,cortex-a8-pmu"},
-	{.compatible = "arm,arm1136-pmu"},
+	{.compatible = "arm,cortex-a7-pmu"},
+	{.compatible = "arm,cortex-a5-pmu"},
+	{.compatible = "arm,arm11mpcore-pmu"},
 	{.compatible = "arm,arm1176-pmu"},
+	{.compatible = "arm,arm1136-pmu"},
 	{},
 };
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 3/9] ARM: pmu: remove unused reservation mechanism
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
  2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
  2012-08-10 17:36 ` [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

The PMU reservation mechanism was originally intended to allow OProfile
and perf-events to co-ordinate over access to the CPU PMU. Since then,
OProfile for ARM has moved to using perf as its backend, so the
reservation code is no longer used.

This patch removes the reservation code for the CPU PMU on ARM.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 MAINTAINERS                  |    1 -
 arch/arm/Kconfig             |    8 +-------
 arch/arm/include/asm/pmu.h   |   34 ----------------------------------
 arch/arm/kernel/Makefile     |    1 -
 arch/arm/kernel/perf_event.c |    8 --------
 arch/arm/kernel/pmu.c        |   36 ------------------------------------
 6 files changed, 1 insertions(+), 87 deletions(-)
 delete mode 100644 arch/arm/kernel/pmu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 94b823f..9dcd1ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -595,7 +595,6 @@ M:	Will Deacon <will.deacon@arm.com>
 S:	Maintained
 F:	arch/arm/kernel/perf_event*
 F:	arch/arm/oprofile/common.c
-F:	arch/arm/kernel/pmu.c
 F:	arch/arm/include/asm/pmu.h
 F:	arch/arm/kernel/hw_breakpoint.c
 F:	arch/arm/include/asm/hw_breakpoint.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e91c7cd..ca05a95 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1185,12 +1185,6 @@ config XSCALE_PMU
 	depends on CPU_XSCALE
 	default y
 
-config CPU_HAS_PMU
-	depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \
-		   (!ARCH_OMAP3 || OMAP3_EMU)
-	default y
-	bool
-
 config MULTI_IRQ_HANDLER
 	bool
 	help
@@ -1763,7 +1757,7 @@ config HIGHPTE
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && CPU_HAS_PMU
+	depends on PERF_EVENTS
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 40d7dff..05e0401 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -49,40 +49,6 @@ struct arm_pmu_platdata {
 	int (*runtime_suspend)(struct device *dev);
 };
 
-#ifdef CONFIG_CPU_HAS_PMU
-
-/**
- * reserve_pmu() - reserve the hardware performance counters
- *
- * Reserve the hardware performance counters in the system for exclusive use.
- * Returns 0 on success or -EBUSY if the lock is already held.
- */
-extern int
-reserve_pmu(enum arm_pmu_type type);
-
-/**
- * release_pmu() - Relinquish control of the performance counters
- *
- * Release the performance counters and allow someone else to use them.
- */
-extern void
-release_pmu(enum arm_pmu_type type);
-
-#else /* CONFIG_CPU_HAS_PMU */
-
-#include <linux/err.h>
-
-static inline int
-reserve_pmu(enum arm_pmu_type type)
-{
-	return -ENODEV;
-}
-
-static inline void
-release_pmu(enum arm_pmu_type type)	{ }
-
-#endif /* CONFIG_CPU_HAS_PMU */
-
 #ifdef CONFIG_HW_PERF_EVENTS
 
 /* The events for a given PMU register set. */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7ad2d5c..cfbe3b4 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
 obj-$(CONFIG_CPU_PJ4)		+= pj4-cp0.o
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
-obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 3aa3388..1ac1531 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -377,7 +377,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
 	}
 
 	pm_runtime_put_sync(&pmu_device->dev);
-	release_pmu(armpmu->type);
 }
 
 static int
@@ -391,12 +390,6 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
 	if (!pmu_device)
 		return -ENODEV;
 
-	err = reserve_pmu(armpmu->type);
-	if (err) {
-		pr_warning("unable to reserve pmu\n");
-		return err;
-	}
-
 	plat = dev_get_platdata(&pmu_device->dev);
 	if (plat && plat->handle_irq)
 		handle_irq = armpmu_platform_irq;
@@ -706,7 +699,6 @@ static void __init cpu_pmu_init(struct arm_pmu *armpmu)
 		raw_spin_lock_init(&events->pmu_lock);
 	}
 	armpmu->get_hw_events = armpmu_get_cpu_events;
-	armpmu->type = ARM_PMU_DEVICE_CPU;
 }
 
 /*
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
deleted file mode 100644
index 2334bf8..0000000
--- a/arch/arm/kernel/pmu.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  linux/arch/arm/kernel/pmu.c
- *
- *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
- *  Copyright (C) 2010 ARM Ltd, Will Deacon
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/pmu.h>
-
-/*
- * PMU locking to ensure mutual exclusion between different subsystems.
- */
-static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
-
-int
-reserve_pmu(enum arm_pmu_type type)
-{
-	return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
-}
-EXPORT_SYMBOL_GPL(reserve_pmu);
-
-void
-release_pmu(enum arm_pmu_type type)
-{
-	clear_bit_unlock(type, pmu_lock);
-}
-EXPORT_SYMBOL_GPL(release_pmu);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (2 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 3/9] ARM: pmu: remove unused reservation mechanism Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-13 14:17   ` Linus Walleij
                     ` (4 more replies)
  2012-08-10 17:36 ` [PATCH 5/9] ARM: perf: remove mysterious compiler barrier Will Deacon
                   ` (5 subsequent siblings)
  9 siblings, 5 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>

The arm_pmu_type enumeration was initially introduced to identify
different PMU types in the system, the usual one being that on the CPU
(ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
the introduction of devicetree bindings for the CPU PMU, the enumeration
is no longer required.

This patch removes the enumeration and updates the various CPU PMU
platform devices so that they no longer pass an .id field referring
to identify the PMU type.

Cc: JD Zheng <jdzheng@broadcom.com>
Cc: Jon Hunter <jon-hunter@ti.com>
Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Signed-off-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
[will: cosmetic edits and actual removal of the enum type]
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/include/asm/pmu.h               |   10 ----------
 arch/arm/mach-bcmring/arch.c             |    3 +--
 arch/arm/mach-omap2/devices.c            |    3 +--
 arch/arm/mach-pxa/devices.c              |    3 +--
 arch/arm/mach-realview/realview_eb.c     |    3 +--
 arch/arm/mach-realview/realview_pb1176.c |    3 +--
 arch/arm/mach-realview/realview_pb11mp.c |    3 +--
 arch/arm/mach-realview/realview_pba8.c   |    3 +--
 arch/arm/mach-realview/realview_pbx.c    |    3 +--
 arch/arm/mach-tegra/devices.c            |    3 +--
 arch/arm/mach-ux500/cpu-db8500.c         |    3 +--
 arch/arm/mach-vexpress/ct-ca9x4.c        |    3 +--
 arch/arm/plat-iop/pmu.c                  |    3 +--
 arch/arm/plat-samsung/devs.c             |    3 +--
 14 files changed, 13 insertions(+), 36 deletions(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 05e0401..fbec73a 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -16,15 +16,6 @@
 #include <linux/perf_event.h>
 
 /*
- * Types of PMUs that can be accessed directly and require mutual
- * exclusion between profiling tools.
- */
-enum arm_pmu_type {
-	ARM_PMU_DEVICE_CPU	= 0,
-	ARM_NUM_PMU_DEVICES,
-};
-
-/*
  * struct arm_pmu_platdata - ARM PMU platform data
  *
  * @handle_irq: an optional handler which will be called from the
@@ -73,7 +64,6 @@ struct pmu_hw_events {
 
 struct arm_pmu {
 	struct pmu	pmu;
-	enum arm_pmu_type type;
 	cpumask_t	active_irqs;
 	char		*name;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 45c97b1..76e7953 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -29,7 +29,6 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
-#include <asm/pmu.h>
 
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
@@ -116,7 +115,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pmu_resource,
 	.num_resources	= 1,
 };
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c00c689..02b9478 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -23,7 +23,6 @@
 #include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
-#include <asm/pmu.h>
 
 #include "iomap.h"
 #include <plat/board.h>
@@ -448,7 +447,7 @@ static struct resource omap3_pmu_resource = {
 
 static struct platform_device omap_pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= 1,
 };
 
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 166eee5..c1f3b12 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -6,7 +6,6 @@
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/i2c/pxa-i2c.h>
 
-#include <asm/pmu.h>
 #include <mach/udc.h>
 #include <mach/pxa3xx-u2d.h>
 #include <mach/pxafb.h>
@@ -42,7 +41,7 @@ static struct resource pxa_resource_pmu = {
 
 struct platform_device pxa_device_pmu = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pxa_resource_pmu,
 	.num_resources	= 1,
 };
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index baf382c..d7a6e9c 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -32,7 +32,6 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -297,7 +296,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index b1d7caf..361f898 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -34,7 +34,6 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -280,7 +279,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= 1,
 	.resource		= &pmu_resource,
 };
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index a98c536..c56bc8d 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -32,7 +32,6 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -263,7 +262,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 5965017..0409375 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -31,7 +31,6 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 
@@ -241,7 +240,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= 1,
 	.resource		= &pmu_resource,
 };
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 3f2f605..97885dc 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -30,7 +30,6 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/smp_twd.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
@@ -280,7 +279,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index c70e65f..61e9603 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -23,7 +23,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/serial_8250.h>
 #include <linux/i2c-tegra.h>
-#include <asm/pmu.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
 #include <mach/dma.h>
@@ -516,7 +515,7 @@ static struct resource tegra_pmu_resources[] = {
 
 struct platform_device tegra_pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(tegra_pmu_resources),
 	.resource	= tegra_pmu_resources,
 };
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index db3c52d..3ee761d 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -19,7 +19,6 @@
 #include <linux/mfd/abx500/ab8500.h>
 
 #include <asm/mach/map.h>
-#include <asm/pmu.h>
 #include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -122,7 +121,7 @@ struct arm_pmu_platdata db8500_pmu_platdata = {
 
 static struct platform_device db8500_pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(db8500_pmu_resources),
 	.resource		= db8500_pmu_resources,
 	.dev.platform_data	= &db8500_pmu_platdata,
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 61c4924..e4073a6 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -13,7 +13,6 @@
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
-#include <asm/pmu.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
@@ -144,7 +143,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(pmu_resources),
 	.resource	= pmu_resources,
 };
diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/plat-iop/pmu.c
index a2024b8..ad9f974 100644
--- a/arch/arm/plat-iop/pmu.c
+++ b/arch/arm/plat-iop/pmu.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <asm/pmu.h>
 #include <mach/irqs.h>
 
 static struct resource pmu_resource = {
@@ -26,7 +25,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pmu_resource,
 	.num_resources	= 1,
 };
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 74e31ce..8154fab 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -33,7 +33,6 @@
 #include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/irq.h>
-#include <asm/pmu.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -1105,7 +1104,7 @@ static struct resource s5p_pmu_resource[] = {
 
 static struct platform_device s5p_device_pmu = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(s5p_pmu_resource),
 	.resource	= s5p_pmu_resource,
 };
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 5/9] ARM: perf: remove mysterious compiler barrier
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (3 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 17:36 ` [PATCH 6/9] ARM: perf: probe devicetree in preference to current CPU Will Deacon
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

There's a rather strange compiler barrier in the PMU disabling code
which was presumably placed there by aliens. There's no valid reason for
the barrier and one can only suspect that it's up to no good.

This patch removes it before it has a chance to spread.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/kernel/perf_event.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 1ac1531..22ed512 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -223,7 +223,6 @@ armpmu_stop(struct perf_event *event, int flags)
 	 */
 	if (!(hwc->state & PERF_HES_STOPPED)) {
 		armpmu->disable(hwc, hwc->idx);
-		barrier(); /* why? */
 		armpmu_event_update(event, hwc, hwc->idx);
 		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	}
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 6/9] ARM: perf: probe devicetree in preference to current CPU
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (4 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 5/9] ARM: perf: remove mysterious compiler barrier Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 17:36 ` [PATCH 7/9] ARM: perf: prepare for moving CPU PMU code into separate file Will Deacon
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

The CPU PMU is probed using the current cpuid information as part of the
early_initcall initialising the architecture perf backend. For
architectures without NMI (such as ARM), this does not need to be
performed early and can be deferred to the driver probe callback. This
also allows us to probe the devicetree in preference to parsing the
current cpuid, which may be invalid on a big.LITTLE multi-cluster
system.

This patch defers the PMU probing and uses the devicetree information
when available.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/kernel/perf_event.c        |  175 ++++++++++++++++++-----------------
 arch/arm/kernel/perf_event_v6.c     |    8 +-
 arch/arm/kernel/perf_event_v7.c     |   22 ++--
 arch/arm/kernel/perf_event_xscale.c |    8 +-
 4 files changed, 110 insertions(+), 103 deletions(-)

diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 22ed512..7c29914 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
+#include <linux/of.h>
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
@@ -610,9 +611,11 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
 	};
 }
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 {
 	armpmu_init(armpmu);
+	pr_info("enabled with %s PMU driver, %d counters available\n",
+			armpmu->name, armpmu->num_events);
 	return perf_pmu_register(&armpmu->pmu, name, type);
 }
 
@@ -621,74 +624,12 @@ int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 #include "perf_event_v6.c"
 #include "perf_event_v7.c"
 
-/*
- * Ensure the PMU has sane values out of reset.
- * This requires SMP to be available, so exists as a separate initcall.
- */
-static int __init
-cpu_pmu_reset(void)
-{
-	if (cpu_pmu && cpu_pmu->reset)
-		return on_each_cpu(cpu_pmu->reset, NULL, 1);
-	return 0;
-}
-arch_initcall(cpu_pmu_reset);
-
-/*
- * PMU platform driver and devicetree bindings.
- */
-static struct of_device_id armpmu_of_device_ids[] = {
-	{.compatible = "arm,cortex-a15-pmu"},
-	{.compatible = "arm,cortex-a9-pmu"},
-	{.compatible = "arm,cortex-a8-pmu"},
-	{.compatible = "arm,cortex-a7-pmu"},
-	{.compatible = "arm,cortex-a5-pmu"},
-	{.compatible = "arm,arm11mpcore-pmu"},
-	{.compatible = "arm,arm1176-pmu"},
-	{.compatible = "arm,arm1136-pmu"},
-	{},
-};
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
-	{.name = "arm-pmu"},
-	{},
-};
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
-	if (!cpu_pmu)
-		return -ENODEV;
-
-	cpu_pmu->plat_device = pdev;
-	return 0;
-}
-
-static const struct dev_pm_ops armpmu_dev_pm_ops = {
-	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
-};
-
-static struct platform_driver armpmu_driver = {
-	.driver		= {
-		.name	= "arm-pmu",
-		.pm	= &armpmu_dev_pm_ops,
-		.of_match_table = armpmu_of_device_ids,
-	},
-	.probe		= armpmu_device_probe,
-	.id_table	= armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
-
 static struct pmu_hw_events *armpmu_get_cpu_events(void)
 {
 	return &__get_cpu_var(cpu_hw_events);
 }
 
-static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	int cpu;
 	for_each_possible_cpu(cpu) {
@@ -697,7 +638,11 @@ static void __init cpu_pmu_init(struct arm_pmu *armpmu)
 		events->used_mask = per_cpu(used_mask, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
 	}
-	armpmu->get_hw_events = armpmu_get_cpu_events;
+	cpu_pmu->get_hw_events = armpmu_get_cpu_events;
+
+	/* Ensure the PMU has sane values out of reset. */
+	if (cpu_pmu && cpu_pmu->reset)
+		on_each_cpu(cpu_pmu->reset, NULL, 1);
 }
 
 /*
@@ -722,41 +667,68 @@ static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
 	.notifier_call = pmu_cpu_notify,
 };
 
+static const struct dev_pm_ops armpmu_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a15-pmu",	.data = armv7_a15_pmu_init},
+	{.compatible = "arm,cortex-a9-pmu",	.data = armv7_a9_pmu_init},
+	{.compatible = "arm,cortex-a8-pmu",	.data = armv7_a8_pmu_init},
+	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
+	{.compatible = "arm,cortex-a5-pmu",	.data = armv7_a5_pmu_init},
+	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
+	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
+	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
+	{},
+};
+
+static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
+	{.name = "arm-pmu"},
+	{},
+};
+
 /*
- * CPU PMU identification and registration.
+ * CPU PMU identification and probing.
  */
-static int __init
-init_hw_perf_events(void)
+static struct arm_pmu *__devinit probe_current_pmu(void)
 {
+	struct arm_pmu *pmu = NULL;
+	int cpu = get_cpu();
 	unsigned long cpuid = read_cpuid_id();
 	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
 	unsigned long part_number = (cpuid & 0xFFF0);
 
+	pr_info("probing PMU on CPU %d\n", cpu);
+
 	/* ARM Ltd CPUs. */
 	if (0x41 == implementor) {
 		switch (part_number) {
 		case 0xB360:	/* ARM1136 */
 		case 0xB560:	/* ARM1156 */
 		case 0xB760:	/* ARM1176 */
-			cpu_pmu = armv6pmu_init();
+			pmu = armv6pmu_init();
 			break;
 		case 0xB020:	/* ARM11mpcore */
-			cpu_pmu = armv6mpcore_pmu_init();
+			pmu = armv6mpcore_pmu_init();
 			break;
 		case 0xC080:	/* Cortex-A8 */
-			cpu_pmu = armv7_a8_pmu_init();
+			pmu = armv7_a8_pmu_init();
 			break;
 		case 0xC090:	/* Cortex-A9 */
-			cpu_pmu = armv7_a9_pmu_init();
+			pmu = armv7_a9_pmu_init();
 			break;
 		case 0xC050:	/* Cortex-A5 */
-			cpu_pmu = armv7_a5_pmu_init();
+			pmu = armv7_a5_pmu_init();
 			break;
 		case 0xC0F0:	/* Cortex-A15 */
-			cpu_pmu = armv7_a15_pmu_init();
+			pmu = armv7_a15_pmu_init();
 			break;
 		case 0xC070:	/* Cortex-A7 */
-			cpu_pmu = armv7_a7_pmu_init();
+			pmu = armv7_a7_pmu_init();
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -764,27 +736,62 @@ init_hw_perf_events(void)
 		part_number = (cpuid >> 13) & 0x7;
 		switch (part_number) {
 		case 1:
-			cpu_pmu = xscale1pmu_init();
+			pmu = xscale1pmu_init();
 			break;
 		case 2:
-			cpu_pmu = xscale2pmu_init();
+			pmu = xscale2pmu_init();
 			break;
 		}
 	}
 
+	put_cpu();
+	return pmu;
+}
+
+static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	struct arm_pmu *(*init_fn)(void);
+	struct device_node *node = pdev->dev.of_node;
+
 	if (cpu_pmu) {
-		pr_info("enabled with %s PMU driver, %d counters available\n",
-			cpu_pmu->name, cpu_pmu->num_events);
-		cpu_pmu_init(cpu_pmu);
-		register_cpu_notifier(&pmu_cpu_notifier);
-		armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+		pr_info("attempt to register multiple PMU devices!");
+		return -ENOSPC;
+	}
+
+	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
+		init_fn = of_id->data;
+		cpu_pmu = init_fn();
 	} else {
-		pr_info("no hardware support available\n");
+		cpu_pmu = probe_current_pmu();
 	}
 
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	cpu_pmu_init(cpu_pmu);
+	register_cpu_notifier(&pmu_cpu_notifier);
+	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+
 	return 0;
 }
-early_initcall(init_hw_perf_events);
+
+static struct platform_driver cpu_pmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.pm	= &armpmu_dev_pm_ops,
+		.of_match_table = cpu_pmu_of_device_ids,
+	},
+	.probe		= cpu_pmu_device_probe,
+	.id_table	= cpu_pmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&cpu_pmu_driver);
+}
+device_initcall(register_pmu_driver);
 
 /*
  * Callchain handling code.
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index c90fcb2..a4328b1 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -664,7 +664,7 @@ static struct arm_pmu armv6pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__devinit armv6pmu_init(void)
 {
 	return &armv6pmu;
 }
@@ -698,17 +698,17 @@ static struct arm_pmu armv6mpcore_pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
 {
 	return &armv6mpcore_pmu;
 }
 #else
-static struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__devinit armv6pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index f04070b..d65a1b8 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1245,7 +1245,7 @@ static struct arm_pmu armv7pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static u32 __init armv7_read_num_pmnc_events(void)
+static u32 __devinit armv7_read_num_pmnc_events(void)
 {
 	u32 nb_cnt;
 
@@ -1256,7 +1256,7 @@ static u32 __init armv7_read_num_pmnc_events(void)
 	return nb_cnt + 1;
 }
 
-static struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A8";
 	armv7pmu.map_event	= armv7_a8_map_event;
@@ -1264,7 +1264,7 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A9";
 	armv7pmu.map_event	= armv7_a9_map_event;
@@ -1272,7 +1272,7 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A5";
 	armv7pmu.map_event	= armv7_a5_map_event;
@@ -1280,7 +1280,7 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A15";
 	armv7pmu.map_event	= armv7_a15_map_event;
@@ -1289,7 +1289,7 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a7_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A7";
 	armv7pmu.map_event	= armv7_a7_map_event;
@@ -1298,27 +1298,27 @@ static struct arm_pmu *__init armv7_a7_pmu_init(void)
 	return &armv7pmu;
 }
 #else
-static struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a7_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index f759fe0..dcc478c 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -449,7 +449,7 @@ static struct arm_pmu xscale1pmu = {
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__devinit xscale1pmu_init(void)
 {
 	return &xscale1pmu;
 }
@@ -816,17 +816,17 @@ static struct arm_pmu xscale2pmu = {
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__devinit xscale2pmu_init(void)
 {
 	return &xscale2pmu;
 }
 #else
-static struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__devinit xscale1pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__devinit xscale2pmu_init(void)
 {
 	return NULL;
 }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 7/9] ARM: perf: prepare for moving CPU PMU code into separate file
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (5 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 6/9] ARM: perf: probe devicetree in preference to current CPU Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 17:36 ` [PATCH 8/9] ARM: perf: move CPU-specific PMU handling " Will Deacon
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

The CPU PMU code is tightly coupled with generic ARM PMU handling code.
This makes it cumbersome when trying to add support for other ARM PMUs
(e.g. interconnect, L2 cache controller, bus) as the generic parts of
the code are not readily reusable.

This patch cleans up perf_event.c so that reusable code is exposed via
header files to other potential PMU drivers. The CPU code is
consistently named to identify it as such and also to prepare for moving
it into a separate file.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/include/asm/perf_event.h   |    9 ++++-
 arch/arm/include/asm/pmu.h          |   11 +++++-
 arch/arm/kernel/perf_event.c        |   69 ++++++++++++++---------------------
 arch/arm/kernel/perf_event_v6.c     |    4 +-
 arch/arm/kernel/perf_event_v7.c     |   10 +++---
 arch/arm/kernel/perf_event_xscale.c |    2 +-
 6 files changed, 53 insertions(+), 52 deletions(-)

diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index e074948..625cd62 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,6 +12,13 @@
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-/* Nothing to see here... */
+/*
+ * The ARMv7 CPU PMU supports up to 32 event counters.
+ */
+#define ARMPMU_MAX_HWEVENTS		32
+
+#define HW_OP_UNSUPPORTED		0xFFFF
+#define C(_x)				PERF_COUNT_HW_CACHE_##_x
+#define CACHE_OP_UNSUPPORTED		0xFFFF
 
 #endif /* __ARM_PERF_EVENT_H__ */
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index fbec73a..a993ad6 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -89,7 +89,9 @@ struct arm_pmu {
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+extern const struct dev_pm_ops armpmu_dev_pm_ops;
+
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type);
 
 u64 armpmu_event_update(struct perf_event *event,
 			struct hw_perf_event *hwc,
@@ -99,6 +101,13 @@ int armpmu_event_set_period(struct perf_event *event,
 			    struct hw_perf_event *hwc,
 			    int idx);
 
+int armpmu_map_event(struct perf_event *event,
+		     const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+		     const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
+						[PERF_COUNT_HW_CACHE_OP_MAX]
+						[PERF_COUNT_HW_CACHE_RESULT_MAX],
+		     u32 raw_event_mask);
+
 #endif /* CONFIG_HW_PERF_EVENTS */
 
 #endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 7c29914..9e3afd1 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -29,26 +29,17 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-/*
- * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
- * another platform that supports more, we need to increase this to be the
- * largest of all platforms.
- *
- * ARMv7 supports up to 32 events:
- *  cycle counter CCNT + 31 events counters CNT0..30.
- *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
- */
-#define ARMPMU_MAX_HWEVENTS		32
+/* Set at runtime when we know what CPU type we are. */
+static struct arm_pmu *cpu_pmu;
 
 static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
 static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
 static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
 
-#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
-
-/* Set at runtime when we know what CPU type we are. */
-static struct arm_pmu *cpu_pmu;
-
+/*
+ * Despite the names, these two functions are CPU-specific and are used
+ * by the OProfile/perf code.
+ */
 const char *perf_pmu_name(void)
 {
 	if (!cpu_pmu)
@@ -69,13 +60,6 @@ int perf_num_counters(void)
 }
 EXPORT_SYMBOL_GPL(perf_num_counters);
 
-#define HW_OP_UNSUPPORTED		0xFFFF
-
-#define C(_x) \
-	PERF_COUNT_HW_CACHE_##_x
-
-#define CACHE_OP_UNSUPPORTED		0xFFFF
-
 static int
 armpmu_map_cache_event(const unsigned (*cache_map)
 				      [PERF_COUNT_HW_CACHE_MAX]
@@ -106,7 +90,7 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 }
 
 static int
-armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
+armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
 	int mapping = (*event_map)[config];
 	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
@@ -118,19 +102,20 @@ armpmu_map_raw_event(u32 raw_event_mask, u64 config)
 	return (int)(config & raw_event_mask);
 }
 
-static int map_cpu_event(struct perf_event *event,
-			 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
-			 const unsigned (*cache_map)
-					[PERF_COUNT_HW_CACHE_MAX]
-					[PERF_COUNT_HW_CACHE_OP_MAX]
-					[PERF_COUNT_HW_CACHE_RESULT_MAX],
-			 u32 raw_event_mask)
+int
+armpmu_map_event(struct perf_event *event,
+		 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+		 const unsigned (*cache_map)
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX],
+		 u32 raw_event_mask)
 {
 	u64 config = event->attr.config;
 
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
-		return armpmu_map_event(event_map, config);
+		return armpmu_map_hw_event(event_map, config);
 	case PERF_TYPE_HW_CACHE:
 		return armpmu_map_cache_event(cache_map, config);
 	case PERF_TYPE_RAW:
@@ -594,6 +579,10 @@ static int armpmu_runtime_suspend(struct device *dev)
 }
 #endif
 
+const struct dev_pm_ops armpmu_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+};
+
 static void __init armpmu_init(struct arm_pmu *armpmu)
 {
 	atomic_set(&armpmu->active_events, 0);
@@ -624,7 +613,7 @@ int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 #include "perf_event_v6.c"
 #include "perf_event_v7.c"
 
-static struct pmu_hw_events *armpmu_get_cpu_events(void)
+static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 {
 	return &__get_cpu_var(cpu_hw_events);
 }
@@ -638,7 +627,7 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 		events->used_mask = per_cpu(used_mask, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
 	}
-	cpu_pmu->get_hw_events = armpmu_get_cpu_events;
+	cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
 
 	/* Ensure the PMU has sane values out of reset. */
 	if (cpu_pmu && cpu_pmu->reset)
@@ -651,8 +640,8 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
  * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
  * junk values out of them.
  */
-static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
-					unsigned long action, void *hcpu)
+static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
+				    unsigned long action, void *hcpu)
 {
 	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
 		return NOTIFY_DONE;
@@ -663,12 +652,8 @@ static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
-	.notifier_call = pmu_cpu_notify,
-};
-
-static const struct dev_pm_ops armpmu_dev_pm_ops = {
-	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
+	.notifier_call = cpu_pmu_notify,
 };
 
 /*
@@ -771,7 +756,7 @@ static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
 
 	cpu_pmu->plat_device = pdev;
 	cpu_pmu_init(cpu_pmu);
-	register_cpu_notifier(&pmu_cpu_notifier);
+	register_cpu_notifier(&cpu_pmu_hotplug_notifier);
 	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
 
 	return 0;
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index a4328b1..6ccc079 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -645,7 +645,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
 
 static int armv6_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv6_perf_map,
+	return armpmu_map_event(event, &armv6_perf_map,
 				&armv6_perf_cache_map, 0xFF);
 }
 
@@ -679,7 +679,7 @@ static struct arm_pmu *__devinit armv6pmu_init(void)
 
 static int armv6mpcore_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv6mpcore_perf_map,
+	return armpmu_map_event(event, &armv6mpcore_perf_map,
 				&armv6mpcore_perf_cache_map, 0xFF);
 }
 
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index d65a1b8..bd4b090 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1204,31 +1204,31 @@ static void armv7pmu_reset(void *info)
 
 static int armv7_a8_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a8_perf_map,
+	return armpmu_map_event(event, &armv7_a8_perf_map,
 				&armv7_a8_perf_cache_map, 0xFF);
 }
 
 static int armv7_a9_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a9_perf_map,
+	return armpmu_map_event(event, &armv7_a9_perf_map,
 				&armv7_a9_perf_cache_map, 0xFF);
 }
 
 static int armv7_a5_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a5_perf_map,
+	return armpmu_map_event(event, &armv7_a5_perf_map,
 				&armv7_a5_perf_cache_map, 0xFF);
 }
 
 static int armv7_a15_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a15_perf_map,
+	return armpmu_map_event(event, &armv7_a15_perf_map,
 				&armv7_a15_perf_cache_map, 0xFF);
 }
 
 static int armv7_a7_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a7_perf_map,
+	return armpmu_map_event(event, &armv7_a7_perf_map,
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index dcc478c..426e19f 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -430,7 +430,7 @@ xscale1pmu_write_counter(int counter, u32 val)
 
 static int xscale_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &xscale_perf_map,
+	return armpmu_map_event(event, &xscale_perf_map,
 				&xscale_perf_cache_map, 0xFF);
 }
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 8/9] ARM: perf: move CPU-specific PMU handling code into separate file
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (6 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 7/9] ARM: perf: prepare for moving CPU PMU code into separate file Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-10 17:36 ` [PATCH 9/9] ARM: perf: move irq registration into pmu implementation Will Deacon
  2012-08-13  9:11 ` [PATCH 0/9] ARM perf updates for 3.7 Hui Wang
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

This patch moves the CPU-specific PMU handling code out of perf_event.c
and into perf_event_cpu.c.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/kernel/Makefile         |    2 +-
 arch/arm/kernel/perf_event.c     |  211 +----------------------------------
 arch/arm/kernel/perf_event_cpu.c |  231 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 233 insertions(+), 211 deletions(-)
 create mode 100644 arch/arm/kernel/perf_event_cpu.c

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index cfbe3b4..1c43214 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -69,7 +69,7 @@ obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
 obj-$(CONFIG_CPU_PJ4)		+= pj4-cp0.o
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o perf_event_cpu.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 9e3afd1..86fd399 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -12,54 +12,15 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
-#include <linux/bitmap.h>
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/perf_event.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/pm_runtime.h>
+#include <linux/uaccess.h>
 
-#include <asm/cputype.h>
-#include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-/* Set at runtime when we know what CPU type we are. */
-static struct arm_pmu *cpu_pmu;
-
-static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
-static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
-static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
-
-/*
- * Despite the names, these two functions are CPU-specific and are used
- * by the OProfile/perf code.
- */
-const char *perf_pmu_name(void)
-{
-	if (!cpu_pmu)
-		return NULL;
-
-	return cpu_pmu->pmu.name;
-}
-EXPORT_SYMBOL_GPL(perf_pmu_name);
-
-int perf_num_counters(void)
-{
-	int max_events = 0;
-
-	if (cpu_pmu != NULL)
-		max_events = cpu_pmu->num_events;
-
-	return max_events;
-}
-EXPORT_SYMBOL_GPL(perf_num_counters);
-
 static int
 armpmu_map_cache_event(const unsigned (*cache_map)
 				      [PERF_COUNT_HW_CACHE_MAX]
@@ -608,176 +569,6 @@ int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 	return perf_pmu_register(&armpmu->pmu, name, type);
 }
 
-/* Include the PMU-specific implementations. */
-#include "perf_event_xscale.c"
-#include "perf_event_v6.c"
-#include "perf_event_v7.c"
-
-static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
-{
-	return &__get_cpu_var(cpu_hw_events);
-}
-
-static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
-{
-	int cpu;
-	for_each_possible_cpu(cpu) {
-		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
-		events->events = per_cpu(hw_events, cpu);
-		events->used_mask = per_cpu(used_mask, cpu);
-		raw_spin_lock_init(&events->pmu_lock);
-	}
-	cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
-
-	/* Ensure the PMU has sane values out of reset. */
-	if (cpu_pmu && cpu_pmu->reset)
-		on_each_cpu(cpu_pmu->reset, NULL, 1);
-}
-
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
-				    unsigned long action, void *hcpu)
-{
-	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
-		return NOTIFY_DONE;
-
-	if (cpu_pmu && cpu_pmu->reset)
-		cpu_pmu->reset(NULL);
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
-	.notifier_call = cpu_pmu_notify,
-};
-
-/*
- * PMU platform driver and devicetree bindings.
- */
-static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
-	{.compatible = "arm,cortex-a15-pmu",	.data = armv7_a15_pmu_init},
-	{.compatible = "arm,cortex-a9-pmu",	.data = armv7_a9_pmu_init},
-	{.compatible = "arm,cortex-a8-pmu",	.data = armv7_a8_pmu_init},
-	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
-	{.compatible = "arm,cortex-a5-pmu",	.data = armv7_a5_pmu_init},
-	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
-	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
-	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
-	{},
-};
-
-static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
-	{.name = "arm-pmu"},
-	{},
-};
-
-/*
- * CPU PMU identification and probing.
- */
-static struct arm_pmu *__devinit probe_current_pmu(void)
-{
-	struct arm_pmu *pmu = NULL;
-	int cpu = get_cpu();
-	unsigned long cpuid = read_cpuid_id();
-	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
-	unsigned long part_number = (cpuid & 0xFFF0);
-
-	pr_info("probing PMU on CPU %d\n", cpu);
-
-	/* ARM Ltd CPUs. */
-	if (0x41 == implementor) {
-		switch (part_number) {
-		case 0xB360:	/* ARM1136 */
-		case 0xB560:	/* ARM1156 */
-		case 0xB760:	/* ARM1176 */
-			pmu = armv6pmu_init();
-			break;
-		case 0xB020:	/* ARM11mpcore */
-			pmu = armv6mpcore_pmu_init();
-			break;
-		case 0xC080:	/* Cortex-A8 */
-			pmu = armv7_a8_pmu_init();
-			break;
-		case 0xC090:	/* Cortex-A9 */
-			pmu = armv7_a9_pmu_init();
-			break;
-		case 0xC050:	/* Cortex-A5 */
-			pmu = armv7_a5_pmu_init();
-			break;
-		case 0xC0F0:	/* Cortex-A15 */
-			pmu = armv7_a15_pmu_init();
-			break;
-		case 0xC070:	/* Cortex-A7 */
-			pmu = armv7_a7_pmu_init();
-			break;
-		}
-	/* Intel CPUs [xscale]. */
-	} else if (0x69 == implementor) {
-		part_number = (cpuid >> 13) & 0x7;
-		switch (part_number) {
-		case 1:
-			pmu = xscale1pmu_init();
-			break;
-		case 2:
-			pmu = xscale2pmu_init();
-			break;
-		}
-	}
-
-	put_cpu();
-	return pmu;
-}
-
-static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id;
-	struct arm_pmu *(*init_fn)(void);
-	struct device_node *node = pdev->dev.of_node;
-
-	if (cpu_pmu) {
-		pr_info("attempt to register multiple PMU devices!");
-		return -ENOSPC;
-	}
-
-	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
-		init_fn = of_id->data;
-		cpu_pmu = init_fn();
-	} else {
-		cpu_pmu = probe_current_pmu();
-	}
-
-	if (!cpu_pmu)
-		return -ENODEV;
-
-	cpu_pmu->plat_device = pdev;
-	cpu_pmu_init(cpu_pmu);
-	register_cpu_notifier(&cpu_pmu_hotplug_notifier);
-	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
-
-	return 0;
-}
-
-static struct platform_driver cpu_pmu_driver = {
-	.driver		= {
-		.name	= "arm-pmu",
-		.pm	= &armpmu_dev_pm_ops,
-		.of_match_table = cpu_pmu_of_device_ids,
-	},
-	.probe		= cpu_pmu_device_probe,
-	.id_table	= cpu_pmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&cpu_pmu_driver);
-}
-device_initcall(register_pmu_driver);
-
 /*
  * Callchain handling code.
  */
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
new file mode 100644
index 0000000..56ddc98
--- /dev/null
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -0,0 +1,231 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+#define pr_fmt(fmt) "CPU PMU: " fmt
+
+#include <linux/bitmap.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <asm/cputype.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
+
+/* Set at runtime when we know what CPU type we are. */
+static struct arm_pmu *cpu_pmu;
+
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
+
+/*
+ * Despite the names, these two functions are CPU-specific and are used
+ * by the OProfile/perf code.
+ */
+const char *perf_pmu_name(void)
+{
+	if (!cpu_pmu)
+		return NULL;
+
+	return cpu_pmu->pmu.name;
+}
+EXPORT_SYMBOL_GPL(perf_pmu_name);
+
+int perf_num_counters(void)
+{
+	int max_events = 0;
+
+	if (cpu_pmu != NULL)
+		max_events = cpu_pmu->num_events;
+
+	return max_events;
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
+/* Include the PMU-specific implementations. */
+#include "perf_event_xscale.c"
+#include "perf_event_v6.c"
+#include "perf_event_v7.c"
+
+static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
+{
+	return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+		events->events = per_cpu(hw_events, cpu);
+		events->used_mask = per_cpu(used_mask, cpu);
+		raw_spin_lock_init(&events->pmu_lock);
+	}
+	cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
+
+	/* Ensure the PMU has sane values out of reset. */
+	if (cpu_pmu && cpu_pmu->reset)
+		on_each_cpu(cpu_pmu->reset, NULL, 1);
+}
+
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
+				    unsigned long action, void *hcpu)
+{
+	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
+		return NOTIFY_DONE;
+
+	if (cpu_pmu && cpu_pmu->reset)
+		cpu_pmu->reset(NULL);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
+	.notifier_call = cpu_pmu_notify,
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a15-pmu",	.data = armv7_a15_pmu_init},
+	{.compatible = "arm,cortex-a9-pmu",	.data = armv7_a9_pmu_init},
+	{.compatible = "arm,cortex-a8-pmu",	.data = armv7_a8_pmu_init},
+	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
+	{.compatible = "arm,cortex-a5-pmu",	.data = armv7_a5_pmu_init},
+	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
+	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
+	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
+	{},
+};
+
+static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
+	{.name = "arm-pmu"},
+	{},
+};
+
+/*
+ * CPU PMU identification and probing.
+ */
+static struct arm_pmu *__devinit probe_current_pmu(void)
+{
+	struct arm_pmu *pmu = NULL;
+	int cpu = get_cpu();
+	unsigned long cpuid = read_cpuid_id();
+	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
+	unsigned long part_number = (cpuid & 0xFFF0);
+
+	pr_info("probing PMU on CPU %d\n", cpu);
+
+	/* ARM Ltd CPUs. */
+	if (0x41 == implementor) {
+		switch (part_number) {
+		case 0xB360:	/* ARM1136 */
+		case 0xB560:	/* ARM1156 */
+		case 0xB760:	/* ARM1176 */
+			pmu = armv6pmu_init();
+			break;
+		case 0xB020:	/* ARM11mpcore */
+			pmu = armv6mpcore_pmu_init();
+			break;
+		case 0xC080:	/* Cortex-A8 */
+			pmu = armv7_a8_pmu_init();
+			break;
+		case 0xC090:	/* Cortex-A9 */
+			pmu = armv7_a9_pmu_init();
+			break;
+		case 0xC050:	/* Cortex-A5 */
+			pmu = armv7_a5_pmu_init();
+			break;
+		case 0xC0F0:	/* Cortex-A15 */
+			pmu = armv7_a15_pmu_init();
+			break;
+		case 0xC070:	/* Cortex-A7 */
+			pmu = armv7_a7_pmu_init();
+			break;
+		}
+	/* Intel CPUs [xscale]. */
+	} else if (0x69 == implementor) {
+		part_number = (cpuid >> 13) & 0x7;
+		switch (part_number) {
+		case 1:
+			pmu = xscale1pmu_init();
+			break;
+		case 2:
+			pmu = xscale2pmu_init();
+			break;
+		}
+	}
+
+	put_cpu();
+	return pmu;
+}
+
+static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	struct arm_pmu *(*init_fn)(void);
+	struct device_node *node = pdev->dev.of_node;
+
+	if (cpu_pmu) {
+		pr_info("attempt to register multiple PMU devices!");
+		return -ENOSPC;
+	}
+
+	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
+		init_fn = of_id->data;
+		cpu_pmu = init_fn();
+	} else {
+		cpu_pmu = probe_current_pmu();
+	}
+
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	cpu_pmu_init(cpu_pmu);
+	register_cpu_notifier(&cpu_pmu_hotplug_notifier);
+	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+
+	return 0;
+}
+
+static struct platform_driver cpu_pmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.pm	= &armpmu_dev_pm_ops,
+		.of_match_table = cpu_pmu_of_device_ids,
+	},
+	.probe		= cpu_pmu_device_probe,
+	.id_table	= cpu_pmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&cpu_pmu_driver);
+}
+device_initcall(register_pmu_driver);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 9/9] ARM: perf: move irq registration into pmu implementation
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (7 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 8/9] ARM: perf: move CPU-specific PMU handling " Will Deacon
@ 2012-08-10 17:36 ` Will Deacon
  2012-08-13  9:11 ` [PATCH 0/9] ARM perf updates for 3.7 Hui Wang
  9 siblings, 0 replies; 29+ messages in thread
From: Will Deacon @ 2012-08-10 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>

This patch moves the CPU-specific IRQ registration and parsing code into
the CPU PMU backend. This is required because a PMU may have more than
one interrupt, which in turn can be either PPI (per-cpu) or SPI
(requiring strict affinity setting at the interrupt distributor).

Signed-off-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
[will: cosmetic edits and reworked interrupt dispatching]
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/include/asm/pmu.h       |    2 +
 arch/arm/kernel/perf_event.c     |   72 ++++++-------------------------------
 arch/arm/kernel/perf_event_cpu.c |   66 ++++++++++++++++++++++++++++++++++-
 3 files changed, 79 insertions(+), 61 deletions(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index a993ad6..a26170d 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -78,6 +78,8 @@ struct arm_pmu {
 	void		(*start)(void);
 	void		(*stop)(void);
 	void		(*reset)(void *);
+	int		(*request_irq)(irq_handler_t handler);
+	void		(*free_irq)(void);
 	int		(*map_event)(struct perf_event *event);
 	int		num_events;
 	atomic_t	active_events;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 86fd399..93971b1 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -297,87 +297,39 @@ validate_group(struct perf_event *event)
 	return 0;
 }
 
-static irqreturn_t armpmu_platform_irq(int irq, void *dev)
+static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
 {
 	struct arm_pmu *armpmu = (struct arm_pmu *) dev;
 	struct platform_device *plat_device = armpmu->plat_device;
 	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
 
-	return plat->handle_irq(irq, dev, armpmu->handle_irq);
+	if (plat && plat->handle_irq)
+		return plat->handle_irq(irq, dev, armpmu->handle_irq);
+	else
+		return armpmu->handle_irq(irq, dev);
 }
 
 static void
 armpmu_release_hardware(struct arm_pmu *armpmu)
 {
-	int i, irq, irqs;
-	struct platform_device *pmu_device = armpmu->plat_device;
-
-	irqs = min(pmu_device->num_resources, num_possible_cpus());
-
-	for (i = 0; i < irqs; ++i) {
-		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
-			continue;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, armpmu);
-	}
-
-	pm_runtime_put_sync(&pmu_device->dev);
+	armpmu->free_irq();
+	pm_runtime_put_sync(&armpmu->plat_device->dev);
 }
 
 static int
 armpmu_reserve_hardware(struct arm_pmu *armpmu)
 {
-	struct arm_pmu_platdata *plat;
-	irq_handler_t handle_irq;
-	int i, err, irq, irqs;
+	int err;
 	struct platform_device *pmu_device = armpmu->plat_device;
 
 	if (!pmu_device)
 		return -ENODEV;
 
-	plat = dev_get_platdata(&pmu_device->dev);
-	if (plat && plat->handle_irq)
-		handle_irq = armpmu_platform_irq;
-	else
-		handle_irq = armpmu->handle_irq;
-
-	irqs = min(pmu_device->num_resources, num_possible_cpus());
-	if (irqs < 1) {
-		pr_err("no irqs for PMUs defined\n");
-		return -ENODEV;
-	}
-
 	pm_runtime_get_sync(&pmu_device->dev);
-
-	for (i = 0; i < irqs; ++i) {
-		err = 0;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq < 0)
-			continue;
-
-		/*
-		 * If we have a single PMU interrupt that we can't shift,
-		 * assume that we're running on a uniprocessor machine and
-		 * continue. Otherwise, continue without this interrupt.
-		 */
-		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
-			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-				    irq, i);
-			continue;
-		}
-
-		err = request_irq(irq, handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "arm-pmu", armpmu);
-		if (err) {
-			pr_err("unable to request IRQ%d for ARM PMU counters\n",
-				irq);
-			armpmu_release_hardware(armpmu);
-			return err;
-		}
-
-		cpumask_set_cpu(i, &armpmu->active_irqs);
+	err = armpmu->request_irq(armpmu_dispatch_irq);
+	if (err) {
+		armpmu_release_hardware(armpmu);
+		return err;
 	}
 
 	return 0;
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 56ddc98..8d7d8d4 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -70,6 +70,67 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return &__get_cpu_var(cpu_hw_events);
 }
 
+static void cpu_pmu_free_irq(void)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, cpu_pmu);
+	}
+}
+
+static int cpu_pmu_request_irq(irq_handler_t handler)
+{
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	if (!pmu_device)
+		return -ENODEV;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
+		pr_err("no irqs for PMUs defined\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < irqs; ++i) {
+		err = 0;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq < 0)
+			continue;
+
+		/*
+		 * If we have a single PMU interrupt that we can't shift,
+		 * assume that we're running on a uniprocessor machine and
+		 * continue. Otherwise, continue without this interrupt.
+		 */
+		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+				    irq, i);
+			continue;
+		}
+
+		err = request_irq(irq, handler, IRQF_NOBALANCING, "arm-pmu",
+				  cpu_pmu);
+		if (err) {
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			return err;
+		}
+
+		cpumask_set_cpu(i, &cpu_pmu->active_irqs);
+	}
+
+	return 0;
+}
+
 static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	int cpu;
@@ -79,7 +140,10 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 		events->used_mask = per_cpu(used_mask, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
 	}
-	cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
+
+	cpu_pmu->get_hw_events	= cpu_pmu_get_cpu_events;
+	cpu_pmu->request_irq	= cpu_pmu_request_irq;
+	cpu_pmu->free_irq	= cpu_pmu_free_irq;
 
 	/* Ensure the PMU has sane values out of reset. */
 	if (cpu_pmu && cpu_pmu->reset)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs
  2012-08-10 17:36 ` [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs Will Deacon
@ 2012-08-10 18:42   ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2012-08-10 18:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/10/2012 12:36 PM, Will Deacon wrote:
> This patch adds separate devicetree bindings for 11MPcore and
> Cortex-{A5,A7,A15} PMUs in preparation for improved devicetree parsing
> in the ARM perf-event CPU PMU driver.
> 
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---

Acked-by: Rob Herring <rob.herring@calxeda.com>


>  Documentation/devicetree/bindings/arm/pmu.txt |    4 ++++
>  arch/arm/kernel/perf_event.c                  |    6 +++++-
>  2 files changed, 9 insertions(+), 1 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
> index 1c044eb..343781b 100644
> --- a/Documentation/devicetree/bindings/arm/pmu.txt
> +++ b/Documentation/devicetree/bindings/arm/pmu.txt
> @@ -7,8 +7,12 @@ representation in the device tree should be done as under:-
>  Required properties:
>  
>  - compatible : should be one of
> +	"arm,cortex-a15-pmu"
>  	"arm,cortex-a9-pmu"
>  	"arm,cortex-a8-pmu"
> +	"arm,cortex-a7-pmu"
> +	"arm,cortex-a5-pmu"
> +	"arm,arm11mpcore-pmu"
>  	"arm,arm1176-pmu"
>  	"arm,arm1136-pmu"
>  - interrupts : 1 combined interrupt or 1 per core.
> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
> index c44647e..3aa3388 100644
> --- a/arch/arm/kernel/perf_event.c
> +++ b/arch/arm/kernel/perf_event.c
> @@ -646,10 +646,14 @@ arch_initcall(cpu_pmu_reset);
>   * PMU platform driver and devicetree bindings.
>   */
>  static struct of_device_id armpmu_of_device_ids[] = {
> +	{.compatible = "arm,cortex-a15-pmu"},
>  	{.compatible = "arm,cortex-a9-pmu"},
>  	{.compatible = "arm,cortex-a8-pmu"},
> -	{.compatible = "arm,arm1136-pmu"},
> +	{.compatible = "arm,cortex-a7-pmu"},
> +	{.compatible = "arm,cortex-a5-pmu"},
> +	{.compatible = "arm,arm11mpcore-pmu"},
>  	{.compatible = "arm,arm1176-pmu"},
> +	{.compatible = "arm,arm1136-pmu"},
>  	{},
>  };
>  
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/9] ARM: PMU: Add runtime PM Support
  2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
@ 2012-08-11 15:09   ` Ming Lei
  2012-08-13 10:40     ` Will Deacon
  0 siblings, 1 reply; 29+ messages in thread
From: Ming Lei @ 2012-08-11 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Aug 11, 2012 at 1:36 AM, Will Deacon <will.deacon@arm.com> wrote:
> From: Jon Hunter <jon-hunter@ti.com>
>
> Add runtime PM support to the ARM PMU driver so that devices such as OMAP
> supporting dynamic PM can use the platform->runtime_* hooks to initialise
> hardware at runtime. Without having these runtime PM hooks in place any
> configuration of the PMU hardware would be lost when low power states are
> entered and hence would prevent PMU from working.
>
> This change also replaces the PMU platform functions enable_irq and disable_irq
> added by Ming Lei with runtime_resume and runtime_suspend funtions. Ming had
> added the enable_irq and disable_irq functions as a method to configure the
> cross trigger interface on OMAP4 for routing the PMU interrupts. By adding
> runtime PM support, we can move the code called by enable_irq and disable_irq
> into the runtime PM callbacks runtime_resume and runtime_suspend.
>
> Cc: Ming Lei <ming.lei@canonical.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@ti.com>
> Signed-off-by: Jon Hunter <jon-hunter@ti.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>  arch/arm/include/asm/pmu.h   |   20 ++++++++++++--------
>  arch/arm/kernel/perf_event.c |   41 +++++++++++++++++++++++++++++++++--------
>  2 files changed, 45 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
> index 4432305..40d7dff 100644
> --- a/arch/arm/include/asm/pmu.h
> +++ b/arch/arm/include/asm/pmu.h
> @@ -31,18 +31,22 @@ enum arm_pmu_type {
>   *     interrupt and passed the address of the low level handler,
>   *     and can be used to implement any platform specific handling
>   *     before or after calling it.
> - * @enable_irq: an optional handler which will be called after
> - *     request_irq and be used to handle some platform specific
> - *     irq enablement
> - * @disable_irq: an optional handler which will be called before
> - *     free_irq and be used to handle some platform specific
> - *     irq disablement
> + * @runtime_resume: an optional handler which will be called by the
> + *     runtime PM framework following a call to pm_runtime_get().
> + *     Note that if pm_runtime_get() is called more than once in
> + *     succession this handler will only be called once.
> + * @runtime_suspend: an optional handler which will be called by the
> + *     runtime PM framework following a call to pm_runtime_put().
> + *     Note that if pm_runtime_get() is called more than once in
> + *     succession this handler will only be called following the
> + *     final call to pm_runtime_put() that actually disables the
> + *     hardware.
>   */
>  struct arm_pmu_platdata {
>         irqreturn_t (*handle_irq)(int irq, void *dev,
>                                   irq_handler_t pmu_handler);
> -       void (*enable_irq)(int irq);
> -       void (*disable_irq)(int irq);
> +       int (*runtime_resume)(struct device *dev);
> +       int (*runtime_suspend)(struct device *dev);
>  };
>
>  #ifdef CONFIG_CPU_HAS_PMU
> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
> index ab243b8..c44647e 100644
> --- a/arch/arm/kernel/perf_event.c
> +++ b/arch/arm/kernel/perf_event.c
> @@ -20,6 +20,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/spinlock.h>
>  #include <linux/uaccess.h>
> +#include <linux/pm_runtime.h>
>
>  #include <asm/cputype.h>
>  #include <asm/irq.h>
> @@ -364,8 +365,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
>  {
>         int i, irq, irqs;
>         struct platform_device *pmu_device = armpmu->plat_device;
> -       struct arm_pmu_platdata *plat =
> -               dev_get_platdata(&pmu_device->dev);
>
>         irqs = min(pmu_device->num_resources, num_possible_cpus());
>
> @@ -373,13 +372,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
>                 if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
>                         continue;
>                 irq = platform_get_irq(pmu_device, i);
> -               if (irq >= 0) {
> -                       if (plat && plat->disable_irq)
> -                               plat->disable_irq(irq);
> +               if (irq >= 0)
>                         free_irq(irq, armpmu);
> -               }
>         }
>
> +       pm_runtime_put_sync(&pmu_device->dev);

One question, each pmu is just inside one cpu core and should be
suspended individually, but looks the above don't support it, do it?

>         release_pmu(armpmu->type);
>  }
>
> @@ -412,6 +409,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
>                 return -ENODEV;
>         }
>
> +       pm_runtime_get_sync(&pmu_device->dev);

Similar with above.


Thanks,
--
Ming Lei

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 0/9] ARM perf updates for 3.7
  2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
                   ` (8 preceding siblings ...)
  2012-08-10 17:36 ` [PATCH 9/9] ARM: perf: move irq registration into pmu implementation Will Deacon
@ 2012-08-13  9:11 ` Hui Wang
  2012-08-13  9:32   ` Will Deacon
  9 siblings, 1 reply; 29+ messages in thread
From: Hui Wang @ 2012-08-13  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will Deacon,

For SMP platforms, each CPU core has an independent PMU, and each PMU 
has a dedicated irq (SPI or PPI). Current perf subsystem framework only 
supports each PMU to have a dedicated SPI irq, and it will support each 
PMU to have a PPI irq (i have seen someone has sent out the patches), 
but there is a situation the subsystem doesn't support yet, the 
situation is multi PMUs share one same SPI irq, e.g. the i.MX6Quad CPU 
has 4 cortex-a9 cores, each core has a PMU, all PMU irqs are routed 
(ORed) to one SPI irq, do you know how to support this situation?

Regards,
Hui.




Will Deacon wrote:
> Hello,
>
> This patch series contains the ARM perf updates I'd like to push for 3.7
> Most of the code is cleanup in preparation for big.LITTLE PMU support,
> where we will need to support different types of CPU PMU on the same SoC.
>
> The PMU probing has changed so that we try to identify the PMU using its
> DT binding before falling back to probing the current core. The unused
> PMU registration mechanism is also removed and platforms registering
> the device have been updated accordingly.
>
> Given that this touches a few platforms, I anticipate sending it via
> arm-soc.
>
> All feedback welcome,
>
> Will
>
>
> Jon Hunter (1):
>   ARM: PMU: Add runtime PM Support
>
> Sudeep KarkadaNagesha (2):
>   ARM: pmu: remove arm_pmu_type enumeration
>   ARM: perf: move irq registration into pmu implementation
>
> Will Deacon (6):
>   ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs
>   ARM: pmu: remove unused reservation mechanism
>   ARM: perf: remove mysterious compiler barrier
>   ARM: perf: probe devicetree in preference to current CPU
>   ARM: perf: prepare for moving CPU PMU code into separate file
>   ARM: perf: move CPU-specific PMU handling code into separate file
>
>  Documentation/devicetree/bindings/arm/pmu.txt |    4 +
>  MAINTAINERS                                   |    1 -
>  arch/arm/Kconfig                              |    8 +-
>  arch/arm/include/asm/perf_event.h             |    9 +-
>  arch/arm/include/asm/pmu.h                    |   77 ++----
>  arch/arm/kernel/Makefile                      |    3 +-
>  arch/arm/kernel/perf_event.c                  |  347 ++++---------------------
>  arch/arm/kernel/perf_event_cpu.c              |  295 +++++++++++++++++++++
>  arch/arm/kernel/perf_event_v6.c               |   12 +-
>  arch/arm/kernel/perf_event_v7.c               |   32 ++--
>  arch/arm/kernel/perf_event_xscale.c           |   10 +-
>  arch/arm/kernel/pmu.c                         |   36 ---
>  arch/arm/mach-bcmring/arch.c                  |    3 +-
>  arch/arm/mach-omap2/devices.c                 |    3 +-
>  arch/arm/mach-pxa/devices.c                   |    3 +-
>  arch/arm/mach-realview/realview_eb.c          |    3 +-
>  arch/arm/mach-realview/realview_pb1176.c      |    3 +-
>  arch/arm/mach-realview/realview_pb11mp.c      |    3 +-
>  arch/arm/mach-realview/realview_pba8.c        |    3 +-
>  arch/arm/mach-realview/realview_pbx.c         |    3 +-
>  arch/arm/mach-tegra/devices.c                 |    3 +-
>  arch/arm/mach-ux500/cpu-db8500.c              |    3 +-
>  arch/arm/mach-vexpress/ct-ca9x4.c             |    3 +-
>  arch/arm/plat-iop/pmu.c                       |    3 +-
>  arch/arm/plat-samsung/devs.c                  |    3 +-
>  25 files changed, 424 insertions(+), 449 deletions(-)
>  create mode 100644 arch/arm/kernel/perf_event_cpu.c
>  delete mode 100644 arch/arm/kernel/pmu.c
>
>   

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 0/9] ARM perf updates for 3.7
  2012-08-13  9:11 ` [PATCH 0/9] ARM perf updates for 3.7 Hui Wang
@ 2012-08-13  9:32   ` Will Deacon
  2012-08-14  1:46     ` Hui Wang
  0 siblings, 1 reply; 29+ messages in thread
From: Will Deacon @ 2012-08-13  9:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 13, 2012 at 10:11:37AM +0100, Hui Wang wrote:
> Hi Will Deacon,

Hello,

> For SMP platforms, each CPU core has an independent PMU, and each PMU 
> has a dedicated irq (SPI or PPI). Current perf subsystem framework only 
> supports each PMU to have a dedicated SPI irq, and it will support each 
> PMU to have a PPI irq (i have seen someone has sent out the patches), 
> but there is a situation the subsystem doesn't support yet, the 
> situation is multi PMUs share one same SPI irq, e.g. the i.MX6Quad CPU 
> has 4 cortex-a9 cores, each core has a PMU, all PMU irqs are routed 
> (ORed) to one SPI irq, do you know how to support this situation?

That's what I like to call a braindead, broken system. Seriously, CPU PMU
interrupts *can only* be handled on the CPU which raised them -- ORing these
things together means ping-ponging the interrupt affinity around until we
find the right guy. There's also the fun case where multiple PMUs assert
simultaneously and I've even heard about platforms where they OR in the
bloody L2 PMU interrupt as well for good measure!

If you have to support such a device, take a look at the ux500 code
(db8500_pmu_handler), but please take all of your profiling numbers with a
pinch of salt. For a quad-core processor, the numbers will probably be even
less accurate.

Also, please go ahead and inflict sufficient injuries to your hardware guys
that they stop this madness!

Will

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/9] ARM: PMU: Add runtime PM Support
  2012-08-11 15:09   ` Ming Lei
@ 2012-08-13 10:40     ` Will Deacon
  2012-08-16 13:56       ` Jon Hunter
  0 siblings, 1 reply; 29+ messages in thread
From: Will Deacon @ 2012-08-13 10:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Aug 11, 2012 at 04:09:51PM +0100, Ming Lei wrote:
> On Sat, Aug 11, 2012 at 1:36 AM, Will Deacon <will.deacon@arm.com> wrote:
> > +       pm_runtime_put_sync(&pmu_device->dev);
> 
> One question, each pmu is just inside one cpu core and should be
> suspended individually, but looks the above don't support it, do it?

I'll let Jon elaborate, but I'm not sure that suspending the individual PMUs
makes much sense if one of them is being used (other than taking the whole
CPU offline). Given that tasks can migrate and perf-events can be across
multiple CPUs, it makes it a lot easier to treat them as a single entity. It
also allows us to implement mutual exclusion using the same hooks and to
manage any common IP (e.g. CTI) at the same time, without having to keep
track of things like the last man standing.

So, unless Jon has some ideas here, it's not something that I consider to be
a real problem.

Will

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
@ 2012-08-13 14:17   ` Linus Walleij
  2012-08-13 21:57   ` Jiandong Zheng
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 29+ messages in thread
From: Linus Walleij @ 2012-08-13 14:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 10, 2012 at 7:36 PM, Will Deacon <will.deacon@arm.com> wrote:

> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
>
> The arm_pmu_type enumeration was initially introduced to identify
> different PMU types in the system, the usual one being that on the CPU
> (ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
> the introduction of devicetree bindings for the CPU PMU, the enumeration
> is no longer required.
>
> This patch removes the enumeration and updates the various CPU PMU
> platform devices so that they no longer pass an .id field referring
> to identify the PMU type.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
  2012-08-13 14:17   ` Linus Walleij
@ 2012-08-13 21:57   ` Jiandong Zheng
  2012-08-14  8:43     ` Sudeep KarkadaNagesha
  2012-08-16 13:59   ` Jon Hunter
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 29+ messages in thread
From: Jiandong Zheng @ 2012-08-13 21:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/10/2012 10:36 AM, Will Deacon wrote:
> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
>
> The arm_pmu_type enumeration was initially introduced to identify
> different PMU types in the system, the usual one being that on the CPU
> (ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
> the introduction of devicetree bindings for the CPU PMU, the enumeration
> is no longer required.
>
> This patch removes the enumeration and updates the various CPU PMU
> platform devices so that they no longer pass an .id field referring
> to identify the PMU type.
>
> Cc: JD Zheng <jdzheng@broadcom.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Signed-off-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
> [will: cosmetic edits and actual removal of the enum type]
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>   arch/arm/include/asm/pmu.h               |   10 ----------
>   arch/arm/mach-bcmring/arch.c             |    3 +--
>   arch/arm/mach-omap2/devices.c            |    3 +--
>   arch/arm/mach-pxa/devices.c              |    3 +--
>   arch/arm/mach-realview/realview_eb.c     |    3 +--
>   arch/arm/mach-realview/realview_pb1176.c |    3 +--
>   arch/arm/mach-realview/realview_pb11mp.c |    3 +--
>   arch/arm/mach-realview/realview_pba8.c   |    3 +--
>   arch/arm/mach-realview/realview_pbx.c    |    3 +--
>   arch/arm/mach-tegra/devices.c            |    3 +--
>   arch/arm/mach-ux500/cpu-db8500.c         |    3 +--
>   arch/arm/mach-vexpress/ct-ca9x4.c        |    3 +--
>   arch/arm/plat-iop/pmu.c                  |    3 +--
>   arch/arm/plat-samsung/devs.c             |    3 +--
>   14 files changed, 13 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
> index 05e0401..fbec73a 100644
> --- a/arch/arm/include/asm/pmu.h
> +++ b/arch/arm/include/asm/pmu.h
> @@ -16,15 +16,6 @@
>   #include <linux/perf_event.h>
>   
>   /*
> - * Types of PMUs that can be accessed directly and require mutual
> - * exclusion between profiling tools.
> - */
> -enum arm_pmu_type {
> -	ARM_PMU_DEVICE_CPU	= 0,
> -	ARM_NUM_PMU_DEVICES,
> -};
> -
> -/*
>    * struct arm_pmu_platdata - ARM PMU platform data
>    *
>    * @handle_irq: an optional handler which will be called from the
> @@ -73,7 +64,6 @@ struct pmu_hw_events {
>   
>   struct arm_pmu {
>   	struct pmu	pmu;
> -	enum arm_pmu_type type;
>   	cpumask_t	active_irqs;
>   	char		*name;
>   	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
> diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
> index 45c97b1..76e7953 100644
> --- a/arch/arm/mach-bcmring/arch.c
> +++ b/arch/arm/mach-bcmring/arch.c
> @@ -29,7 +29,6 @@
>   #include <asm/setup.h>
>   #include <asm/mach-types.h>
>   #include <asm/mach/time.h>
> -#include <asm/pmu.h>
>   
>   #include <asm/mach/arch.h>
>   #include <mach/dma.h>
> @@ -116,7 +115,7 @@ static struct resource pmu_resource = {
>   
>   static struct platform_device pmu_device = {
>   	.name		= "arm-pmu",
> -	.id		= ARM_PMU_DEVICE_CPU,
> +	.id		= -1,
>   	.resource	= &pmu_resource,
>   	.num_resources	= 1,
>   };
>
Isn't it clearer to define a meaningful name for "-1", esp. if "-1" is 
being checked somewhere else?

Regards,
JD

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 0/9] ARM perf updates for 3.7
  2012-08-13  9:32   ` Will Deacon
@ 2012-08-14  1:46     ` Hui Wang
  2013-02-28  6:54       ` i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7) Dirk Behme
  0 siblings, 1 reply; 29+ messages in thread
From: Hui Wang @ 2012-08-14  1:46 UTC (permalink / raw)
  To: linux-arm-kernel

Will Deacon wrote:
> On Mon, Aug 13, 2012 at 10:11:37AM +0100, Hui Wang wrote:
>   
>> Hi Will Deacon,
>>     
>
> Hello,
>
>   
>> For SMP platforms, each CPU core has an independent PMU, and each PMU 
>> has a dedicated irq (SPI or PPI). Current perf subsystem framework only 
>> supports each PMU to have a dedicated SPI irq, and it will support each 
>> PMU to have a PPI irq (i have seen someone has sent out the patches), 
>> but there is a situation the subsystem doesn't support yet, the 
>> situation is multi PMUs share one same SPI irq, e.g. the i.MX6Quad CPU 
>> has 4 cortex-a9 cores, each core has a PMU, all PMU irqs are routed 
>> (ORed) to one SPI irq, do you know how to support this situation?
>>     
>
> That's what I like to call a braindead, broken system. Seriously, CPU PMU
> interrupts *can only* be handled on the CPU which raised them -- ORing these
> things together means ping-ponging the interrupt affinity around until we
> find the right guy. There's also the fun case where multiple PMUs assert
> simultaneously and I've even heard about platforms where they OR in the
> bloody L2 PMU interrupt as well for good measure!
>
> If you have to support such a device, take a look at the ux500 code
> (db8500_pmu_handler), but please take all of your profiling numbers with a
> pinch of salt. For a quad-core processor, the numbers will probably be even
> less accurate.
>
> Also, please go ahead and inflict sufficient injuries to your hardware guys
> that they stop this madness!
>   
Got it, thanks for the information, it is very useful.

Regards,
Hui.


> Will
>
>   

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-13 21:57   ` Jiandong Zheng
@ 2012-08-14  8:43     ` Sudeep KarkadaNagesha
  2012-08-14 16:53       ` Jiandong Zheng
  0 siblings, 1 reply; 29+ messages in thread
From: Sudeep KarkadaNagesha @ 2012-08-14  8:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jiandong,

On 13/08/12 22:57, Jiandong Zheng wrote:
> On 8/10/2012 10:36 AM, Will Deacon wrote:
>> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
>>    static struct platform_device pmu_device = {
>>    	.name		= "arm-pmu",
>> -	.id		= ARM_PMU_DEVICE_CPU,
>> +	.id		= -1,
>>    	.resource	= &pmu_resource,
>>    	.num_resources	= 1,
>>    };
>>
> Isn't it clearer to define a meaningful name for "-1", esp. if "-1" is
> being checked somewhere else?

No platform_device->id is not being referred anywhere. 
ARM_PMU_DEVICE_CPU was initially assigned to id to identify different 
PMU types through platform_device->id variable but was never used.

Also for all new platforms that might support multiple PMUs, we can use 
device tree to identify them.

Regards,
Sudeep

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-14  8:43     ` Sudeep KarkadaNagesha
@ 2012-08-14 16:53       ` Jiandong Zheng
  0 siblings, 0 replies; 29+ messages in thread
From: Jiandong Zheng @ 2012-08-14 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/14/2012 1:43 AM, Sudeep KarkadaNagesha wrote:
> Hi Jiandong,
>
> On 13/08/12 22:57, Jiandong Zheng wrote:
>> On 8/10/2012 10:36 AM, Will Deacon wrote:
>>> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
>>>    static struct platform_device pmu_device = {
>>>        .name        = "arm-pmu",
>>> -    .id        = ARM_PMU_DEVICE_CPU,
>>> +    .id        = -1,
>>>        .resource    = &pmu_resource,
>>>        .num_resources    = 1,
>>>    };
>>>
>> Isn't it clearer to define a meaningful name for "-1", esp. if "-1" is
>> being checked somewhere else?
>
> No platform_device->id is not being referred anywhere. 
> ARM_PMU_DEVICE_CPU was initially assigned to id to identify different 
> PMU types through platform_device->id variable but was never used.
>
> Also for all new platforms that might support multiple PMUs, we can 
> use device tree to identify them.
>
Seems it is just a field not in use. Even though I still prefer 
something like "ARM_PMU_DEFAULT_ID" to "-1", I am OK with "-1" as well.

Acked-by: Jiandong Zheng <jdzheng@broadcom.com>

Thanks,
JD

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/9] ARM: PMU: Add runtime PM Support
  2012-08-13 10:40     ` Will Deacon
@ 2012-08-16 13:56       ` Jon Hunter
  0 siblings, 0 replies; 29+ messages in thread
From: Jon Hunter @ 2012-08-16 13:56 UTC (permalink / raw)
  To: linux-arm-kernel


On 08/13/2012 05:40 AM, Will Deacon wrote:
> On Sat, Aug 11, 2012 at 04:09:51PM +0100, Ming Lei wrote:
>> On Sat, Aug 11, 2012 at 1:36 AM, Will Deacon <will.deacon@arm.com> wrote:
>>> +       pm_runtime_put_sync(&pmu_device->dev);
>>
>> One question, each pmu is just inside one cpu core and should be
>> suspended individually, but looks the above don't support it, do it?
> 
> I'll let Jon elaborate, but I'm not sure that suspending the individual PMUs
> makes much sense if one of them is being used (other than taking the whole
> CPU offline). Given that tasks can migrate and perf-events can be across
> multiple CPUs, it makes it a lot easier to treat them as a single entity. It
> also allows us to implement mutual exclusion using the same hooks and to
> manage any common IP (e.g. CTI) at the same time, without having to keep
> track of things like the last man standing.
> 
> So, unless Jon has some ideas here, it's not something that I consider to be
> a real problem.

So from an OMAP3/4 perspective (which is the only device so far using
these runtime PM callbacks that I know of), it does not add any value to
suspend each PMU individually. For OMAP3/4, if one or more PMU is active
then we need to power up additional power domains and we need to keep
them powered until all PMUs are no longer in use.

For OMAP5 (which I have started testing) does not need other power
domains apart from the CPU power domain. So this could make more sense,
but I have not tried this yet. For now I think it is ok to keep as is
and then we can always change later to optimise for newer devices or
architectures if we think that they would benefit from this.

Cheers
Jon

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
  2012-08-13 14:17   ` Linus Walleij
  2012-08-13 21:57   ` Jiandong Zheng
@ 2012-08-16 13:59   ` Jon Hunter
  2012-08-17 14:08   ` Jon Hunter
  2012-08-23  5:45   ` Kukjin Kim
  4 siblings, 0 replies; 29+ messages in thread
From: Jon Hunter @ 2012-08-16 13:59 UTC (permalink / raw)
  To: linux-arm-kernel


On 08/10/2012 12:36 PM, Will Deacon wrote:
> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
> 
> The arm_pmu_type enumeration was initially introduced to identify
> different PMU types in the system, the usual one being that on the CPU
> (ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
> the introduction of devicetree bindings for the CPU PMU, the enumeration
> is no longer required.
> 
> This patch removes the enumeration and updates the various CPU PMU
> platform devices so that they no longer pass an .id field referring
> to identify the PMU type.

Acked-by: Jon Hunter <jon-hunter@ti.com>

Cheers
Jon

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
                     ` (2 preceding siblings ...)
  2012-08-16 13:59   ` Jon Hunter
@ 2012-08-17 14:08   ` Jon Hunter
  2012-08-20  9:01     ` Will Deacon
  2012-08-23  5:45   ` Kukjin Kim
  4 siblings, 1 reply; 29+ messages in thread
From: Jon Hunter @ 2012-08-17 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will, Tony,

On 08/10/2012 12:36 PM, Will Deacon wrote:
> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
> 
> The arm_pmu_type enumeration was initially introduced to identify
> different PMU types in the system, the usual one being that on the CPU
> (ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
> the introduction of devicetree bindings for the CPU PMU, the enumeration
> is no longer required.
> 
> This patch removes the enumeration and updates the various CPU PMU
> platform devices so that they no longer pass an .id field referring
> to identify the PMU type.

[snip]

> diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
> index c00c689..02b9478 100644
> --- a/arch/arm/mach-omap2/devices.c
> +++ b/arch/arm/mach-omap2/devices.c
> @@ -23,7 +23,6 @@
>  #include <mach/irqs.h>
>  #include <asm/mach-types.h>
>  #include <asm/mach/map.h>
> -#include <asm/pmu.h>
>  
>  #include "iomap.h"
>  #include <plat/board.h>
> @@ -448,7 +447,7 @@ static struct resource omap3_pmu_resource = {
>  
>  static struct platform_device omap_pmu_device = {
>  	.name		= "arm-pmu",
> -	.id		= ARM_PMU_DEVICE_CPU,
> +	.id		= -1,
>  	.num_resources	= 1,
>  };

I know that I have already ack-ed the change and it is fine with me,
however, I see a potential merge conflict here with my patch [1]
(assuming that these all go into v3.7) where I am moving the above
structure.

For testing I have rebased my series on top of this series and it is
working well so far on OMAP4460.

I am hoping to get the next version of my series for omap out next week.
However, before I did I wanted to ask how we should handle the above
change. Should I submit my series as rebased on top of this?

Thanks
Jon

[1]
https://github.com/jonhunter/linux/commit/6a07e3aa21f956bea7858704c224b7f50d25e1c0

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-17 14:08   ` Jon Hunter
@ 2012-08-20  9:01     ` Will Deacon
  2012-08-20 13:05       ` Jon Hunter
  0 siblings, 1 reply; 29+ messages in thread
From: Will Deacon @ 2012-08-20  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 17, 2012 at 03:08:51PM +0100, Jon Hunter wrote:
> Hi Will, Tony,

Hi Jon [adding Arnd],

> On 08/10/2012 12:36 PM, Will Deacon wrote:
> > diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
> > index c00c689..02b9478 100644
> > --- a/arch/arm/mach-omap2/devices.c
> > +++ b/arch/arm/mach-omap2/devices.c
> > @@ -23,7 +23,6 @@
> >  #include <mach/irqs.h>
> >  #include <asm/mach-types.h>
> >  #include <asm/mach/map.h>
> > -#include <asm/pmu.h>
> >  
> >  #include "iomap.h"
> >  #include <plat/board.h>
> > @@ -448,7 +447,7 @@ static struct resource omap3_pmu_resource = {
> >  
> >  static struct platform_device omap_pmu_device = {
> >  	.name		= "arm-pmu",
> > -	.id		= ARM_PMU_DEVICE_CPU,
> > +	.id		= -1,
> >  	.num_resources	= 1,
> >  };
> 
> I know that I have already ack-ed the change and it is fine with me,
> however, I see a potential merge conflict here with my patch [1]
> (assuming that these all go into v3.7) where I am moving the above
> structure.

Are your patches queued anywhere other than your tree? If not, then I could
ask Arnd to pull the perf changes into their own branch in arm-soc and you
could rebase onto that.

> For testing I have rebased my series on top of this series and it is
> working well so far on OMAP4460.

Great, thanks. Can I add your tested-by to the patches please?

Will

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-20  9:01     ` Will Deacon
@ 2012-08-20 13:05       ` Jon Hunter
  0 siblings, 0 replies; 29+ messages in thread
From: Jon Hunter @ 2012-08-20 13:05 UTC (permalink / raw)
  To: linux-arm-kernel


On 08/20/2012 04:01 AM, Will Deacon wrote:
> On Fri, Aug 17, 2012 at 03:08:51PM +0100, Jon Hunter wrote:
>> Hi Will, Tony,
> 
> Hi Jon [adding Arnd],
> 
>> On 08/10/2012 12:36 PM, Will Deacon wrote:
>>> diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
>>> index c00c689..02b9478 100644
>>> --- a/arch/arm/mach-omap2/devices.c
>>> +++ b/arch/arm/mach-omap2/devices.c
>>> @@ -23,7 +23,6 @@
>>>  #include <mach/irqs.h>
>>>  #include <asm/mach-types.h>
>>>  #include <asm/mach/map.h>
>>> -#include <asm/pmu.h>
>>>  
>>>  #include "iomap.h"
>>>  #include <plat/board.h>
>>> @@ -448,7 +447,7 @@ static struct resource omap3_pmu_resource = {
>>>  
>>>  static struct platform_device omap_pmu_device = {
>>>  	.name		= "arm-pmu",
>>> -	.id		= ARM_PMU_DEVICE_CPU,
>>> +	.id		= -1,
>>>  	.num_resources	= 1,
>>>  };
>>
>> I know that I have already ack-ed the change and it is fine with me,
>> however, I see a potential merge conflict here with my patch [1]
>> (assuming that these all go into v3.7) where I am moving the above
>> structure.
> 
> Are your patches queued anywhere other than your tree? If not, then I could
> ask Arnd to pull the perf changes into their own branch in arm-soc and you
> could rebase onto that.

No just my tree for now, so that would work for me.

>> For testing I have rebased my series on top of this series and it is
>> working well so far on OMAP4460.
> 
> Great, thanks. Can I add your tested-by to the patches please?

Yes, you can add my tested-by. I will also test on omap3 and omap4430 too.

Cheers
Jon

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration
  2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
                     ` (3 preceding siblings ...)
  2012-08-17 14:08   ` Jon Hunter
@ 2012-08-23  5:45   ` Kukjin Kim
  4 siblings, 0 replies; 29+ messages in thread
From: Kukjin Kim @ 2012-08-23  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

Will Deacon wrote:
> 
> From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
> 
> The arm_pmu_type enumeration was initially introduced to identify
> different PMU types in the system, the usual one being that on the CPU
> (ARM_PMU_DEVICE_CPU). With the removal of the PMU reservation code and
> the introduction of devicetree bindings for the CPU PMU, the enumeration
> is no longer required.
> 
> This patch removes the enumeration and updates the various CPU PMU
> platform devices so that they no longer pass an .id field referring
> to identify the PMU type.
> 
> Cc: JD Zheng <jdzheng@broadcom.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>

Acked-by: Kukjin Kim <kgene.kim@samsung.com>

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

> Cc: Pawel Moll <pawel.moll@arm.com>
> Signed-off-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
> [will: cosmetic edits and actual removal of the enum type]
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>  arch/arm/include/asm/pmu.h               |   10 ----------
>  arch/arm/mach-bcmring/arch.c             |    3 +--
>  arch/arm/mach-omap2/devices.c            |    3 +--
>  arch/arm/mach-pxa/devices.c              |    3 +--
>  arch/arm/mach-realview/realview_eb.c     |    3 +--
>  arch/arm/mach-realview/realview_pb1176.c |    3 +--
>  arch/arm/mach-realview/realview_pb11mp.c |    3 +--
>  arch/arm/mach-realview/realview_pba8.c   |    3 +--
>  arch/arm/mach-realview/realview_pbx.c    |    3 +--
>  arch/arm/mach-tegra/devices.c            |    3 +--
>  arch/arm/mach-ux500/cpu-db8500.c         |    3 +--
>  arch/arm/mach-vexpress/ct-ca9x4.c        |    3 +--
>  arch/arm/plat-iop/pmu.c                  |    3 +--
>  arch/arm/plat-samsung/devs.c             |    3 +--
>  14 files changed, 13 insertions(+), 36 deletions(-)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7)
  2012-08-14  1:46     ` Hui Wang
@ 2013-02-28  6:54       ` Dirk Behme
  2013-02-28  7:27         ` Shawn Guo
  2013-02-28  7:38         ` i.MX6Quad PMU irq handling Hui Wang
  0 siblings, 2 replies; 29+ messages in thread
From: Dirk Behme @ 2013-02-28  6:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Hui,

On 14.08.2012 03:46, Hui Wang wrote:
> Will Deacon wrote:
>> On Mon, Aug 13, 2012 at 10:11:37AM +0100, Hui Wang wrote:
>>   
>>> Hi Will Deacon,
>>>     
>> Hello,
>>
>>   
>>> For SMP platforms, each CPU core has an independent PMU, and each PMU 
>>> has a dedicated irq (SPI or PPI). Current perf subsystem framework only 
>>> supports each PMU to have a dedicated SPI irq, and it will support each 
>>> PMU to have a PPI irq (i have seen someone has sent out the patches), 
>>> but there is a situation the subsystem doesn't support yet, the 
>>> situation is multi PMUs share one same SPI irq, e.g. the i.MX6Quad CPU 
>>> has 4 cortex-a9 cores, each core has a PMU, all PMU irqs are routed 
>>> (ORed) to one SPI irq, do you know how to support this situation?
>>>     
>> That's what I like to call a braindead, broken system. Seriously, CPU PMU
>> interrupts *can only* be handled on the CPU which raised them -- ORing these
>> things together means ping-ponging the interrupt affinity around until we
>> find the right guy. There's also the fun case where multiple PMUs assert
>> simultaneously and I've even heard about platforms where they OR in the
>> bloody L2 PMU interrupt as well for good measure!
>>
>> If you have to support such a device, take a look at the ux500 code
>> (db8500_pmu_handler), but please take all of your profiling numbers with a
>> pinch of salt. For a quad-core processor, the numbers will probably be even
>> less accurate.
>>
>> Also, please go ahead and inflict sufficient injuries to your hardware guys
>> that they stop this madness!
>>   
> Got it, thanks for the information, it is very useful.

Above you mention the the i.MX6Quad CPU.

Have you done any work/patches for the i.MX6Quad PMU to work with the 
ORed PMU irq?

Have you talked with the Freescale hardware guys "that they stop this 
madness"?

We are facing some issues using perf top on the i.MX6Quad:

http://www.spinics.net/lists/arm-kernel/msg227042.html

Many thanks and best regards

dirk

^ permalink raw reply	[flat|nested] 29+ messages in thread

* i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7)
  2013-02-28  6:54       ` i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7) Dirk Behme
@ 2013-02-28  7:27         ` Shawn Guo
  2013-02-28  7:38         ` i.MX6Quad PMU irq handling Hui Wang
  1 sibling, 0 replies; 29+ messages in thread
From: Shawn Guo @ 2013-02-28  7:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 28, 2013 at 07:54:59AM +0100, Dirk Behme wrote:
> Have you talked with the Freescale hardware guys "that they stop
> this madness"?

The feedback had gone to Freescale design team, and will be fixed
in the future project.

Shawn

^ permalink raw reply	[flat|nested] 29+ messages in thread

* i.MX6Quad PMU irq handling
  2013-02-28  6:54       ` i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7) Dirk Behme
  2013-02-28  7:27         ` Shawn Guo
@ 2013-02-28  7:38         ` Hui Wang
  1 sibling, 0 replies; 29+ messages in thread
From: Hui Wang @ 2013-02-28  7:38 UTC (permalink / raw)
  To: linux-arm-kernel

Dirk Behme wrote:
> Hi Hui,
>
> On 14.08.2012 03:46, Hui Wang wrote:
>> Will Deacon wrote:
>>> On Mon, Aug 13, 2012 at 10:11:37AM +0100, Hui Wang wrote:
>>>  
>>>> Hi Will Deacon,
>>>>     
>>> Hello,
>>>
>>>  
>>>> For SMP platforms, each CPU core has an independent PMU, and each 
>>>> PMU has a dedicated irq (SPI or PPI). Current perf subsystem 
>>>> framework only supports each PMU to have a dedicated SPI irq, and 
>>>> it will support each PMU to have a PPI irq (i have seen someone has 
>>>> sent out the patches), but there is a situation the subsystem 
>>>> doesn't support yet, the situation is multi PMUs share one same SPI 
>>>> irq, e.g. the i.MX6Quad CPU has 4 cortex-a9 cores, each core has a 
>>>> PMU, all PMU irqs are routed (ORed) to one SPI irq, do you know how 
>>>> to support this situation?
>>>>     
>>> That's what I like to call a braindead, broken system. Seriously, 
>>> CPU PMU
>>> interrupts *can only* be handled on the CPU which raised them -- 
>>> ORing these
>>> things together means ping-ponging the interrupt affinity around 
>>> until we
>>> find the right guy. There's also the fun case where multiple PMUs 
>>> assert
>>> simultaneously and I've even heard about platforms where they OR in the
>>> bloody L2 PMU interrupt as well for good measure!
>>>
>>> If you have to support such a device, take a look at the ux500 code
>>> (db8500_pmu_handler), but please take all of your profiling numbers 
>>> with a
>>> pinch of salt. For a quad-core processor, the numbers will probably 
>>> be even
>>> less accurate.
>>>
>>> Also, please go ahead and inflict sufficient injuries to your 
>>> hardware guys
>>> that they stop this madness!
>>>   
>> Got it, thanks for the information, it is very useful.
>
> Above you mention the the i.MX6Quad CPU.
>
> Have you done any work/patches for the i.MX6Quad PMU to work with the 
> ORed PMU irq?
Not yet. i implement a pmu_handler similar to db8500_pmu_handler, but it 
can't work stable on the imx6q. With the increasing number of cpu cores, 
the situation is worse.

>
> Have you talked with the Freescale hardware guys "that they stop this 
> madness"?
As Shawn said, this issue has been reported to FSL.


Regards,
Hui.
>
> We are facing some issues using perf top on the i.MX6Quad:
>
> http://www.spinics.net/lists/arm-kernel/msg227042.html
>
> Many thanks and best regards
>
> dirk
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2013-02-28  7:38 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
2012-08-11 15:09   ` Ming Lei
2012-08-13 10:40     ` Will Deacon
2012-08-16 13:56       ` Jon Hunter
2012-08-10 17:36 ` [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs Will Deacon
2012-08-10 18:42   ` Rob Herring
2012-08-10 17:36 ` [PATCH 3/9] ARM: pmu: remove unused reservation mechanism Will Deacon
2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
2012-08-13 14:17   ` Linus Walleij
2012-08-13 21:57   ` Jiandong Zheng
2012-08-14  8:43     ` Sudeep KarkadaNagesha
2012-08-14 16:53       ` Jiandong Zheng
2012-08-16 13:59   ` Jon Hunter
2012-08-17 14:08   ` Jon Hunter
2012-08-20  9:01     ` Will Deacon
2012-08-20 13:05       ` Jon Hunter
2012-08-23  5:45   ` Kukjin Kim
2012-08-10 17:36 ` [PATCH 5/9] ARM: perf: remove mysterious compiler barrier Will Deacon
2012-08-10 17:36 ` [PATCH 6/9] ARM: perf: probe devicetree in preference to current CPU Will Deacon
2012-08-10 17:36 ` [PATCH 7/9] ARM: perf: prepare for moving CPU PMU code into separate file Will Deacon
2012-08-10 17:36 ` [PATCH 8/9] ARM: perf: move CPU-specific PMU handling " Will Deacon
2012-08-10 17:36 ` [PATCH 9/9] ARM: perf: move irq registration into pmu implementation Will Deacon
2012-08-13  9:11 ` [PATCH 0/9] ARM perf updates for 3.7 Hui Wang
2012-08-13  9:32   ` Will Deacon
2012-08-14  1:46     ` Hui Wang
2013-02-28  6:54       ` i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7) Dirk Behme
2013-02-28  7:27         ` Shawn Guo
2013-02-28  7:38         ` i.MX6Quad PMU irq handling Hui Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.