]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] OProfile: ARM/XScale1 PMU support fix
authorZwane Mwaikambo <zwane@arm.linux.org.uk>
Thu, 10 Feb 2005 06:41:13 +0000 (22:41 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 10 Feb 2005 06:41:13 +0000 (22:41 -0800)
Richard Purdie provided a patch to fix support for XScale1 processors (this
is the PMU version i never had access to initially), we weren't clearing
the overflow flags after an overflow interrupt had triggered resulting in
no additional interrupts occuring.  Additionally i've added basic power
management support.

Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/arm/oprofile/common.c
arch/arm/oprofile/op_arm_model.h
arch/arm/oprofile/op_model_xscale.c

index 53dacfcefe5b14d980af3a7eeffbebe19c7c1b58..615a3ccfea5cbe5bc5715d7d5cdbb75ac9fac214 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/oprofile.h>
 #include <linux/errno.h>
 #include <asm/semaphore.h>
+#include <linux/sysdev.h>
 
 #include "op_counter.h"
 #include "op_arm_model.h"
@@ -25,6 +26,26 @@ static void pmu_stop(void);
 static int pmu_create_files(struct super_block *, struct dentry *);
 
 #ifdef CONFIG_PM
+static int pmu_suspend(struct sys_device *dev, u32 state)
+{
+       if (pmu_enabled)
+               pmu_stop();
+       return 0;
+}
+
+static int pmu_resume(struct sys_device *dev)
+{
+       if (pmu_enabled)
+               pmu_start();
+       return 0;
+}
+
+static struct sysdev_class oprofile_sysclass = {
+       set_kset_name("oprofile"),
+       .resume         = pmu_resume,
+       .suspend        = pmu_suspend,
+};
+
 static struct sys_device device_oprofile = {
        .id             = 0,
        .cls            = &oprofile_sysclass,
@@ -35,14 +56,14 @@ static int __init init_driverfs(void)
        int ret;
 
        if (!(ret = sysdev_class_register(&oprofile_sysclass)))
-               ret = sys_device_register(&device_oprofile);
+               ret = sysdev_register(&device_oprofile);
 
        return ret;
 }
 
-static void __exit exit_driverfs(void)
+static void  exit_driverfs(void)
 {
-       sys_device_unregister(&device_oprofile);
+       sysdev_unregister(&device_oprofile);
        sysdev_class_unregister(&oprofile_sysclass);
 }
 #else
@@ -105,8 +126,7 @@ static void pmu_stop(void)
        up(&pmu_sem);
 }
 
-int __init
-pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec)
+int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec)
 {
        init_MUTEX(&pmu_sem);
 
index 8a04cbe59d4b397ea4516b650249d0bad5dfebc7..2d4caf4781ad466d0f539878bc1462ecb730630d 100644 (file)
@@ -24,6 +24,6 @@ struct op_arm_model_spec {
 extern struct op_arm_model_spec op_xscale_spec;
 #endif
 
-extern int pmu_init(struct oprofile_operations **ops, struct op_arm_model_spec *spec);
+extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
 extern void pmu_exit(void);
 #endif /* OP_ARM_MODEL_H */
index a44282e828cf082525b762c4b057e9520abd4fdb..e0f0b320d76cda9129bb7fcd675b9f08b2f080f9 100644 (file)
@@ -42,6 +42,9 @@
 #ifdef CONFIG_ARCH_IOP331
 #define XSCALE_PMU_IRQ  IRQ_IOP331_CORE_PMU
 #endif
+#ifdef CONFIG_ARCH_PXA
+#define XSCALE_PMU_IRQ  IRQ_PMU
+#endif
 
 /*
  * Different types of events that can be counted by the XScale PMU
@@ -305,9 +308,9 @@ static void inline __xsc1_check_ctrs(void)
        /*       Overflow bit gets cleared. There's no workaround.       */
        /*       Fixed in B stepping or later                            */
 
-       pmnc &= ~(PMU_ENABLE | pmu->cnt_ovf[PMN0] | pmu->cnt_ovf[PMN1] |
-               pmu->cnt_ovf[CCNT]);
-       write_pmnc(pmnc);
+       /* Write the value back to clear the overflow flags. Overflow */
+       /* flags remain in pmnc for use below */
+       write_pmnc(pmnc & ~PMU_ENABLE);
 
        for (i = CCNT; i <= PMN1; i++) {
                if (!(pmu->int_mask[i] & pmu->int_enable))