struct filter_pred      **preds;
 };
 
-#define events_for_each(event)                                         \
-       for (event = __start_ftrace_events;                             \
-            (unsigned long)event < (unsigned long)__stop_ftrace_events; \
-            event++)
-
 struct filter_pred;
 
 typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
        return 0;
 }
 
-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 struct list_head ftrace_events;
 
 extern const char *__start___trace_bprintk_fmt[];
 extern const char *__stop___trace_bprintk_fmt[];
 
 
 static DEFINE_MUTEX(event_mutex);
 
+LIST_HEAD(ftrace_events);
+
 int trace_define_field(struct ftrace_event_call *call, char *type,
                       char *name, int offset, int size)
 {
 
 static void ftrace_clear_events(void)
 {
-       struct ftrace_event_call *call = (void *)__start_ftrace_events;
-
+       struct ftrace_event_call *call;
 
-       while ((unsigned long)call < (unsigned long)__stop_ftrace_events) {
+       list_for_each_entry(call, &ftrace_events, list) {
 
                if (call->enabled) {
                        call->enabled = 0;
                        call->unregfunc();
                }
-               call++;
        }
 }
 
 
 static int ftrace_set_clr_event(char *buf, int set)
 {
-       struct ftrace_event_call *call = __start_ftrace_events;
+       struct ftrace_event_call *call;
        char *event = NULL, *sub = NULL, *match;
        int ret = -EINVAL;
 
        }
 
        mutex_lock(&event_mutex);
-       for_each_event(call) {
+       list_for_each_entry(call, &ftrace_events, list) {
 
                if (!call->name || !call->regfunc)
                        continue;
 static void *
 t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct ftrace_event_call *call = m->private;
-       struct ftrace_event_call *next = call;
+       struct list_head *list = m->private;
+       struct ftrace_event_call *call;
 
        (*pos)++;
 
        for (;;) {
-               if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
+               if (list == &ftrace_events)
                        return NULL;
 
+               call = list_entry(list, struct ftrace_event_call, list);
+
                /*
                 * The ftrace subsystem is for showing formats only.
                 * They can not be enabled or disabled via the event files.
                if (call->regfunc)
                        break;
 
-               call++;
-               next = call;
+               list = list->next;
        }
 
-       m->private = ++next;
+       m->private = list->next;
 
        return call;
 }
 static void *
 s_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct ftrace_event_call *call = m->private;
-       struct ftrace_event_call *next;
+       struct list_head *list = m->private;
+       struct ftrace_event_call *call;
 
        (*pos)++;
 
  retry:
-       if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
+       if (list == &ftrace_events)
                return NULL;
 
+       call = list_entry(list, struct ftrace_event_call, list);
+
        if (!call->enabled) {
-               call++;
+               list = list->next;
                goto retry;
        }
 
-       next = call;
-       m->private = ++next;
+       m->private = list->next;
 
        return call;
 }
        if (!ret) {
                struct seq_file *m = file->private_data;
 
-               m->private = __start_ftrace_events;
+               m->private = ftrace_events.next;
        }
        return ret;
 }
        return 0;
 }
 
+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++)
+
 static __init int event_trace_init(void)
 {
-       struct ftrace_event_call *call = __start_ftrace_events;
+       struct ftrace_event_call *call;
        struct dentry *d_tracer;
        struct dentry *entry;
        struct dentry *d_events;
                /* The linker may leave blanks */
                if (!call->name)
                        continue;
+               list_add(&call->list, &ftrace_events);
                event_create_dir(call, d_events);
        }
 
 
 
 void filter_free_subsystem_preds(struct event_subsystem *system)
 {
-       struct ftrace_event_call *call = __start_ftrace_events;
+       struct ftrace_event_call *call;
        int i;
 
        if (system->n_preds) {
                system->n_preds = 0;
        }
 
-       events_for_each(call) {
+       list_for_each_entry(call, &ftrace_events, list) {
                if (!call->define_fields)
                        continue;
 
 int filter_add_subsystem_pred(struct event_subsystem *system,
                              struct filter_pred *pred)
 {
-       struct ftrace_event_call *call = __start_ftrace_events;
+       struct ftrace_event_call *call;
 
        if (system->n_preds && !pred->compound)
                filter_free_subsystem_preds(system);
 
        system->preds[system->n_preds] = pred;
 
-       events_for_each(call) {
+       list_for_each_entry(call, &ftrace_events, list) {
                int err;
 
                if (!call->define_fields)