#ifdef CONFIG_DYNAMIC_FTRACE
 
+static int trace_selftest_test_probe1_cnt;
+static void trace_selftest_test_probe1_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe1_cnt++;
+}
+
+static int trace_selftest_test_probe2_cnt;
+static void trace_selftest_test_probe2_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe2_cnt++;
+}
+
+static int trace_selftest_test_probe3_cnt;
+static void trace_selftest_test_probe3_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe3_cnt++;
+}
+
+static int trace_selftest_test_global_cnt;
+static void trace_selftest_test_global_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_global_cnt++;
+}
+
+static int trace_selftest_test_dyn_cnt;
+static void trace_selftest_test_dyn_func(unsigned long ip,
+                                        unsigned long pip)
+{
+       trace_selftest_test_dyn_cnt++;
+}
+
+static struct ftrace_ops test_probe1 = {
+       .func                   = trace_selftest_test_probe1_func,
+};
+
+static struct ftrace_ops test_probe2 = {
+       .func                   = trace_selftest_test_probe2_func,
+};
+
+static struct ftrace_ops test_probe3 = {
+       .func                   = trace_selftest_test_probe3_func,
+};
+
+static struct ftrace_ops test_global = {
+       .func                   = trace_selftest_test_global_func,
+       .flags                  = FTRACE_OPS_FL_GLOBAL,
+};
+
+static void print_counts(void)
+{
+       printk("(%d %d %d %d %d) ",
+              trace_selftest_test_probe1_cnt,
+              trace_selftest_test_probe2_cnt,
+              trace_selftest_test_probe3_cnt,
+              trace_selftest_test_global_cnt,
+              trace_selftest_test_dyn_cnt);
+}
+
+static void reset_counts(void)
+{
+       trace_selftest_test_probe1_cnt = 0;
+       trace_selftest_test_probe2_cnt = 0;
+       trace_selftest_test_probe3_cnt = 0;
+       trace_selftest_test_global_cnt = 0;
+       trace_selftest_test_dyn_cnt = 0;
+}
+
+static int trace_selftest_ops(int cnt)
+{
+       int save_ftrace_enabled = ftrace_enabled;
+       struct ftrace_ops *dyn_ops;
+       char *func1_name;
+       char *func2_name;
+       int len1;
+       int len2;
+       int ret = -1;
+
+       printk(KERN_CONT "PASSED\n");
+       pr_info("Testing dynamic ftrace ops #%d: ", cnt);
+
+       ftrace_enabled = 1;
+       reset_counts();
+
+       /* Handle PPC64 '.' name */
+       func1_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
+       func2_name = "*" __stringify(DYN_FTRACE_TEST_NAME2);
+       len1 = strlen(func1_name);
+       len2 = strlen(func2_name);
+
+       /*
+        * Probe 1 will trace function 1.
+        * Probe 2 will trace function 2.
+        * Probe 3 will trace functions 1 and 2.
+        */
+       ftrace_set_filter(&test_probe1, func1_name, len1, 1);
+       ftrace_set_filter(&test_probe2, func2_name, len2, 1);
+       ftrace_set_filter(&test_probe3, func1_name, len1, 1);
+       ftrace_set_filter(&test_probe3, func2_name, len2, 0);
+
+       register_ftrace_function(&test_probe1);
+       register_ftrace_function(&test_probe2);
+       register_ftrace_function(&test_probe3);
+       register_ftrace_function(&test_global);
+
+       DYN_FTRACE_TEST_NAME();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe2_cnt != 0)
+               goto out;
+       if (trace_selftest_test_probe3_cnt != 1)
+               goto out;
+       if (trace_selftest_test_global_cnt == 0)
+               goto out;
+
+       DYN_FTRACE_TEST_NAME2();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe2_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe3_cnt != 2)
+               goto out;
+
+       /* Add a dynamic probe */
+       dyn_ops = kzalloc(sizeof(*dyn_ops), GFP_KERNEL);
+       if (!dyn_ops) {
+               printk("MEMORY ERROR ");
+               goto out;
+       }
+
+       dyn_ops->func = trace_selftest_test_dyn_func;
+
+       register_ftrace_function(dyn_ops);
+
+       trace_selftest_test_global_cnt = 0;
+
+       DYN_FTRACE_TEST_NAME();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe2_cnt != 1)
+               goto out_free;
+       if (trace_selftest_test_probe3_cnt != 3)
+               goto out_free;
+       if (trace_selftest_test_global_cnt == 0)
+               goto out;
+       if (trace_selftest_test_dyn_cnt == 0)
+               goto out_free;
+
+       DYN_FTRACE_TEST_NAME2();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe2_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe3_cnt != 4)
+               goto out_free;
+
+       ret = 0;
+ out_free:
+       unregister_ftrace_function(dyn_ops);
+       kfree(dyn_ops);
+
+ out:
+       /* Purposely unregister in the same order */
+       unregister_ftrace_function(&test_probe1);
+       unregister_ftrace_function(&test_probe2);
+       unregister_ftrace_function(&test_probe3);
+       unregister_ftrace_function(&test_global);
+
+       /* Make sure everything is off */
+       reset_counts();
+       DYN_FTRACE_TEST_NAME();
+       DYN_FTRACE_TEST_NAME();
+
+       if (trace_selftest_test_probe1_cnt ||
+           trace_selftest_test_probe2_cnt ||
+           trace_selftest_test_probe3_cnt ||
+           trace_selftest_test_global_cnt ||
+           trace_selftest_test_dyn_cnt)
+               ret = -1;
+
+       ftrace_enabled = save_ftrace_enabled;
+
+       return ret;
+}
+
 /* Test dynamic code modification and ftrace filters */
 int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
                                           struct trace_array *tr,
 
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
-       trace->reset(tr);
        tracing_start();
 
        /* we should only have one item */
        if (!ret && count != 1) {
+               trace->reset(tr);
                printk(KERN_CONT ".. filter failed count=%ld ..", count);
                ret = -1;
                goto out;
        }
 
+       /* Test the ops with global tracing running */
+       ret = trace_selftest_ops(1);
+       trace->reset(tr);
+
  out:
        ftrace_enabled = save_ftrace_enabled;
        tracer_enabled = save_tracer_enabled;
        /* Enable tracing on all functions again */
        ftrace_set_global_filter(NULL, 0, 1);
 
+       /* Test the ops with global tracing off */
+       if (!ret)
+               ret = trace_selftest_ops(2);
+
        return ret;
 }
 #else