Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / arch / i386 / oprofile / nmi_timer_int.c
index 930a1127bb309e0ff9030384f452e1641d59ea96..1418e36ae7aba63e0274b45618370142ceb4b53d 100644 (file)
 #include <linux/errno.h>
 #include <linux/oprofile.h>
 #include <linux/rcupdate.h>
-
+#include <linux/kdebug.h>
 
 #include <asm/nmi.h>
 #include <asm/apic.h>
 #include <asm/ptrace.h>
  
-static int nmi_timer_callback(struct pt_regs * regs, int cpu)
+static int profile_timer_exceptions_notify(struct notifier_block *self,
+                                          unsigned long val, void *data)
 {
-       oprofile_add_sample(regs, 0);
-       return 1;
+       struct die_args *args = (struct die_args *)data;
+       int ret = NOTIFY_DONE;
+
+       switch(val) {
+       case DIE_NMI:
+               oprofile_add_sample(args->regs, 0);
+               ret = NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return ret;
 }
 
+static struct notifier_block profile_timer_exceptions_nb = {
+       .notifier_call = profile_timer_exceptions_notify,
+       .next = NULL,
+       .priority = 0
+};
+
 static int timer_start(void)
 {
-       disable_timer_nmi_watchdog();
-       set_nmi_callback(nmi_timer_callback);
+       if (register_die_notifier(&profile_timer_exceptions_nb))
+               return 1;
        return 0;
 }
 
 
 static void timer_stop(void)
 {
-       enable_timer_nmi_watchdog();
-       unset_nmi_callback();
+       unregister_die_notifier(&profile_timer_exceptions_nb);
        synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
 
 int __init op_nmi_timer_init(struct oprofile_operations * ops)
 {
-       extern int nmi_active;
-
-       if (nmi_active <= 0)
+       if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
                return -ENODEV;
 
        ops->start = timer_start;