]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/trace/trace_selftest.c
Merge branch 'fix/hda' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6-omap-h63xx.git] / kernel / trace / trace_selftest.c
index 90bc752a7580b3d4800417d2f7a28abe604c1d65..bc8e80a86bca4c0cf730fcf6b7bc568f2808f7e7 100644 (file)
@@ -13,6 +13,7 @@ static inline int trace_valid_entry(struct trace_entry *entry)
        case TRACE_STACK:
        case TRACE_PRINT:
        case TRACE_SPECIAL:
+       case TRACE_BRANCH:
                return 1;
        }
        return 0;
@@ -22,10 +23,20 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
 {
        struct ring_buffer_event *event;
        struct trace_entry *entry;
+       unsigned int loops = 0;
 
        while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) {
                entry = ring_buffer_event_data(event);
 
+               /*
+                * The ring buffer is a size of trace_buf_size, if
+                * we loop more than the size, there's something wrong
+                * with the ring buffer.
+                */
+               if (loops++ > trace_buf_size) {
+                       printk(KERN_CONT ".. bad ring buffer ");
+                       goto failed;
+               }
                if (!trace_valid_entry(entry)) {
                        printk(KERN_CONT ".. invalid entry %d ",
                                entry->type);
@@ -51,18 +62,27 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
        int cpu, ret = 0;
 
        /* Don't allow flipping of max traces now */
-       raw_local_irq_save(flags);
+       local_irq_save(flags);
        __raw_spin_lock(&ftrace_max_lock);
 
        cnt = ring_buffer_entries(tr->buffer);
 
+       /*
+        * The trace_test_buffer_cpu runs a while loop to consume all data.
+        * If the calling tracer is broken, and is constantly filling
+        * the buffer, this will run forever, and hard lock the box.
+        * We disable the ring buffer while we do this test to prevent
+        * a hard lock up.
+        */
+       tracing_off();
        for_each_possible_cpu(cpu) {
                ret = trace_test_buffer_cpu(tr, cpu);
                if (ret)
                        break;
        }
+       tracing_on();
        __raw_spin_unlock(&ftrace_max_lock);
-       raw_local_irq_restore(flags);
+       local_irq_restore(flags);
 
        if (count)
                *count = cnt;
@@ -70,6 +90,11 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
        return ret;
 }
 
+static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)
+{
+       printk(KERN_WARNING "Failed to init %s tracer, init returned %d\n",
+               trace->name, init_ret);
+}
 #ifdef CONFIG_FUNCTION_TRACER
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -110,8 +135,11 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
        ftrace_set_filter(func_name, strlen(func_name), 1);
 
        /* enable tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               goto out;
+       }
 
        /* Sleep for a 1/10 of a second */
        msleep(100);
@@ -134,13 +162,13 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
        msleep(100);
 
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        ftrace_enabled = 0;
 
        /* 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) {
@@ -148,6 +176,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
                ret = -1;
                goto out;
        }
+
  out:
        ftrace_enabled = save_ftrace_enabled;
        tracer_enabled = save_tracer_enabled;
@@ -180,18 +209,22 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
        ftrace_enabled = 1;
        tracer_enabled = 1;
 
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               goto out;
+       }
+
        /* Sleep for a 1/10 of a second */
        msleep(100);
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        ftrace_enabled = 0;
 
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
        trace->reset(tr);
+       tracing_start();
 
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
@@ -223,8 +256,12 @@ trace_selftest_startup_irqsoff(struct tracer *trace, struct trace_array *tr)
        int ret;
 
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return ret;
+       }
+
        /* reset the max latency */
        tracing_max_latency = 0;
        /* disable interrupts for a bit */
@@ -232,13 +269,13 @@ trace_selftest_startup_irqsoff(struct tracer *trace, struct trace_array *tr)
        udelay(100);
        local_irq_enable();
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check both trace buffers */
        ret = trace_test_buffer(tr, NULL);
        if (!ret)
                ret = trace_test_buffer(&max_tr, &count);
        trace->reset(tr);
+       tracing_start();
 
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
@@ -259,9 +296,26 @@ trace_selftest_startup_preemptoff(struct tracer *trace, struct trace_array *tr)
        unsigned long count;
        int ret;
 
+       /*
+        * Now that the big kernel lock is no longer preemptable,
+        * and this is called with the BKL held, it will always
+        * fail. If preemption is already disabled, simply
+        * pass the test. When the BKL is removed, or becomes
+        * preemptible again, we will once again test this,
+        * so keep it in.
+        */
+       if (preempt_count()) {
+               printk(KERN_CONT "can not test ... force ");
+               return 0;
+       }
+
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return ret;
+       }
+
        /* reset the max latency */
        tracing_max_latency = 0;
        /* disable preemption for a bit */
@@ -269,13 +323,13 @@ trace_selftest_startup_preemptoff(struct tracer *trace, struct trace_array *tr)
        udelay(100);
        preempt_enable();
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check both trace buffers */
        ret = trace_test_buffer(tr, NULL);
        if (!ret)
                ret = trace_test_buffer(&max_tr, &count);
        trace->reset(tr);
+       tracing_start();
 
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
@@ -296,9 +350,25 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
        unsigned long count;
        int ret;
 
+       /*
+        * Now that the big kernel lock is no longer preemptable,
+        * and this is called with the BKL held, it will always
+        * fail. If preemption is already disabled, simply
+        * pass the test. When the BKL is removed, or becomes
+        * preemptible again, we will once again test this,
+        * so keep it in.
+        */
+       if (preempt_count()) {
+               printk(KERN_CONT "can not test ... force ");
+               return 0;
+       }
+
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               goto out;
+       }
 
        /* reset the max latency */
        tracing_max_latency = 0;
@@ -312,27 +382,30 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
        local_irq_enable();
 
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check both trace buffers */
        ret = trace_test_buffer(tr, NULL);
-       if (ret)
+       if (ret) {
+               tracing_start();
                goto out;
+       }
 
        ret = trace_test_buffer(&max_tr, &count);
-       if (ret)
+       if (ret) {
+               tracing_start();
                goto out;
+       }
 
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
                ret = -1;
+               tracing_start();
                goto out;
        }
 
        /* do the test by disabling interrupts first this time */
        tracing_max_latency = 0;
-       tr->ctrl = 1;
-       trace->ctrl_update(tr);
+       tracing_start();
        preempt_disable();
        local_irq_disable();
        udelay(100);
@@ -341,8 +414,7 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
        local_irq_enable();
 
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check both trace buffers */
        ret = trace_test_buffer(tr, NULL);
        if (ret)
@@ -358,6 +430,7 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
 
  out:
        trace->reset(tr);
+       tracing_start();
        tracing_max_latency = save_max;
 
        return ret;
@@ -423,8 +496,12 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
        wait_for_completion(&isrt);
 
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return ret;
+       }
+
        /* reset the max latency */
        tracing_max_latency = 0;
 
@@ -448,8 +525,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
        msleep(100);
 
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check both trace buffers */
        ret = trace_test_buffer(tr, NULL);
        if (!ret)
@@ -457,6 +533,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 
 
        trace->reset(tr);
+       tracing_start();
 
        tracing_max_latency = save_max;
 
@@ -480,16 +557,20 @@ trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr
        int ret;
 
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return ret;
+       }
+
        /* Sleep for a 1/10 of a second */
        msleep(100);
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
        trace->reset(tr);
+       tracing_start();
 
        if (!ret && !count) {
                printk(KERN_CONT ".. no entries found ..");
@@ -508,17 +589,48 @@ trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr)
        int ret;
 
        /* start the tracing */
-       tr->ctrl = 1;
-       trace->init(tr);
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return 0;
+       }
+
        /* Sleep for a 1/10 of a second */
        msleep(100);
        /* stop the tracing. */
-       tr->ctrl = 0;
-       trace->ctrl_update(tr);
+       tracing_stop();
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
        trace->reset(tr);
+       tracing_start();
 
        return ret;
 }
 #endif /* CONFIG_SYSPROF_TRACER */
+
+#ifdef CONFIG_BRANCH_TRACER
+int
+trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr)
+{
+       unsigned long count;
+       int ret;
+
+       /* start the tracing */
+       ret = trace->init(tr);
+       if (ret) {
+               warn_failed_init_tracer(trace, ret);
+               return ret;
+       }
+
+       /* Sleep for a 1/10 of a second */
+       msleep(100);
+       /* stop the tracing. */
+       tracing_stop();
+       /* check the trace buffer */
+       ret = trace_test_buffer(tr, &count);
+       trace->reset(tr);
+       tracing_start();
+
+       return ret;
+}
+#endif /* CONFIG_BRANCH_TRACER */