int             id;
        int             (*raw_init)(void);
        int             (*show_format)(struct trace_seq *s);
+
+#ifdef CONFIG_EVENT_PROFILE
+       atomic_t        profile_count;
+       int             (*profile_enable)(struct ftrace_event_call *);
+       void            (*profile_disable)(struct ftrace_event_call *);
+#endif
 };
 
 void event_trace_printk(unsigned long ip, const char *fmt, ...);
 extern struct ftrace_event_call __start_ftrace_events[];
 extern struct ftrace_event_call __stop_ftrace_events[];
 
+#define for_each_event(event)                                          \
+       for (event = __start_ftrace_events;                             \
+            (unsigned long)event < (unsigned long)__stop_ftrace_events; \
+            event++)
+
 extern const char *__start___trace_bprintk_fmt[];
 extern const char *__stop___trace_bprintk_fmt[];
 
 
--- /dev/null
+/*
+ * trace event based perf counter profiling
+ *
+ * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ */
+
+#include "trace.h"
+
+int ftrace_profile_enable(int event_id)
+{
+       struct ftrace_event_call *event;
+
+       for_each_event(event) {
+               if (event->id == event_id)
+                       return event->profile_enable(event);
+       }
+
+       return -EINVAL;
+}
+
+void ftrace_profile_disable(int event_id)
+{
+       struct ftrace_event_call *event;
+
+       for_each_event(event) {
+               if (event->id == event_id)
+                       return event->profile_disable(event);
+       }
+}
+
 
 
 static DEFINE_MUTEX(event_mutex);
 
-#define events_for_each(event)                                         \
-       for (event = __start_ftrace_events;                             \
-            (unsigned long)event < (unsigned long)__stop_ftrace_events; \
-            event++)
-
 static void ftrace_clear_events(void)
 {
        struct ftrace_event_call *call = (void *)__start_ftrace_events;
        }
 
        mutex_lock(&event_mutex);
-       events_for_each(call) {
+       for_each_event(call) {
 
                if (!call->name || !call->regfunc)
                        continue;
        if (!d_events)
                return 0;
 
-       events_for_each(call) {
+       for_each_event(call) {
                /* The linker may leave blanks */
                if (!call->name)
                        continue;
 
 #undef TP_FMT
 #define TP_FMT(fmt, args...)   fmt "\n", ##args
 
+#ifdef CONFIG_EVENT_PROFILE
+#define _TRACE_PROFILE(call, proto, args)                              \
+static void ftrace_profile_##call(proto)                               \
+{                                                                      \
+       extern void perf_tpcounter_event(int);                          \
+       perf_tpcounter_event(event_##call.id);                          \
+}                                                                      \
+                                                                       \
+static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
+{                                                                      \
+       int ret = 0;                                                    \
+                                                                       \
+       if (!atomic_inc_return(&call->profile_count))                   \
+               ret = register_trace_##call(ftrace_profile_##call);     \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
+{                                                                      \
+       if (atomic_add_negative(-1, &call->profile_count))              \
+               unregister_trace_##call(ftrace_profile_##call);         \
+}
+
+#define _TRACE_PROFILE_INIT(call)                                      \
+       .profile_count = ATOMIC_INIT(-1),                               \
+       .profile_enable = ftrace_profile_enable_##call,                 \
+       .profile_disable = ftrace_profile_disable_##call,
+
+#else
+#define _TRACE_PROFILE(call, proto, args)
+#define _TRACE_PROFILE_INIT(call)
+#endif
+
 #define _TRACE_FORMAT(call, proto, args, fmt)                          \
 static void ftrace_event_##call(proto)                                 \
 {                                                                      \
 #undef TRACE_FORMAT
 #define TRACE_FORMAT(call, proto, args, fmt)                           \
 _TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt))          \
+_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args))                      \
 static struct ftrace_event_call __used                                 \
 __attribute__((__aligned__(4)))                                                \
 __attribute__((section("_ftrace_events"))) event_##call = {            \
        .raw_init               = ftrace_init_event_##call,             \
        .regfunc                = ftrace_reg_event_##call,              \
        .unregfunc              = ftrace_unreg_event_##call,            \
+       _TRACE_PROFILE_INIT(call)                                       \
 }
 
 #undef __entry
 
 #undef TRACE_EVENT
 #define TRACE_EVENT(call, proto, args, tstruct, assign, print)         \
+_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args))                      \
                                                                        \
 static struct ftrace_event_call event_##call;                          \
                                                                        \
        .regfunc                = ftrace_raw_reg_event_##call,          \
        .unregfunc              = ftrace_raw_unreg_event_##call,        \
        .show_format            = ftrace_format_##call,                 \
+       _TRACE_PROFILE_INIT(call)                                       \
 }
+
+#include <trace/trace_event_types.h>
+
+#undef _TRACE_PROFILE
+#undef _TRACE_PROFILE_INIT
+