scsi: ufs: core: Fix divide by zero in ufshcd_map_queues()
[platform/kernel/linux-starfive.git] / tools / tracing / rtla / src / osnoise.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
4  */
5
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <pthread.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15
16 #include "osnoise.h"
17 #include "utils.h"
18
19 /*
20  * osnoise_get_cpus - return the original "osnoise/cpus" content
21  *
22  * It also saves the value to be restored.
23  */
24 char *osnoise_get_cpus(struct osnoise_context *context)
25 {
26         if (context->curr_cpus)
27                 return context->curr_cpus;
28
29         if (context->orig_cpus)
30                 return context->orig_cpus;
31
32         context->orig_cpus = tracefs_instance_file_read(NULL, "osnoise/cpus", NULL);
33
34         /*
35          * The error value (NULL) is the same for tracefs_instance_file_read()
36          * and this functions, so:
37          */
38         return context->orig_cpus;
39 }
40
41 /*
42  * osnoise_set_cpus - configure osnoise to run on *cpus
43  *
44  * "osnoise/cpus" file is used to set the cpus in which osnoise/timerlat
45  * will run. This function opens this file, saves the current value,
46  * and set the cpus passed as argument.
47  */
48 int osnoise_set_cpus(struct osnoise_context *context, char *cpus)
49 {
50         char *orig_cpus = osnoise_get_cpus(context);
51         char buffer[1024];
52         int retval;
53
54         if (!orig_cpus)
55                 return -1;
56
57         context->curr_cpus = strdup(cpus);
58         if (!context->curr_cpus)
59                 return -1;
60
61         snprintf(buffer, 1024, "%s\n", cpus);
62
63         debug_msg("setting cpus to %s from %s", cpus, context->orig_cpus);
64
65         retval = tracefs_instance_file_write(NULL, "osnoise/cpus", buffer);
66         if (retval < 0) {
67                 free(context->curr_cpus);
68                 context->curr_cpus = NULL;
69                 return -1;
70         }
71
72         return 0;
73 }
74
75 /*
76  * osnoise_restore_cpus - restore the original "osnoise/cpus"
77  *
78  * osnoise_set_cpus() saves the original data for the "osnoise/cpus"
79  * file. This function restore the original config it was previously
80  * modified.
81  */
82 void osnoise_restore_cpus(struct osnoise_context *context)
83 {
84         int retval;
85
86         if (!context->orig_cpus)
87                 return;
88
89         if (!context->curr_cpus)
90                 return;
91
92         /* nothing to do? */
93         if (!strcmp(context->orig_cpus, context->curr_cpus))
94                 goto out_done;
95
96         debug_msg("restoring cpus to %s", context->orig_cpus);
97
98         retval = tracefs_instance_file_write(NULL, "osnoise/cpus", context->orig_cpus);
99         if (retval < 0)
100                 err_msg("could not restore original osnoise cpus\n");
101
102 out_done:
103         free(context->curr_cpus);
104         context->curr_cpus = NULL;
105 }
106
107 /*
108  * osnoise_put_cpus - restore cpus config and cleanup data
109  */
110 void osnoise_put_cpus(struct osnoise_context *context)
111 {
112         osnoise_restore_cpus(context);
113
114         if (!context->orig_cpus)
115                 return;
116
117         free(context->orig_cpus);
118         context->orig_cpus = NULL;
119 }
120
121 /*
122  * osnoise_read_ll_config - read a long long value from a config
123  *
124  * returns -1 on error.
125  */
126 static long long osnoise_read_ll_config(char *rel_path)
127 {
128         long long retval;
129         char *buffer;
130
131         buffer = tracefs_instance_file_read(NULL, rel_path, NULL);
132         if (!buffer)
133                 return -1;
134
135         /* get_llong_from_str returns -1 on error */
136         retval = get_llong_from_str(buffer);
137
138         debug_msg("reading %s returned %lld\n", rel_path, retval);
139
140         free(buffer);
141
142         return retval;
143 }
144
145 /*
146  * osnoise_write_ll_config - write a long long value to a config in rel_path
147  *
148  * returns -1 on error.
149  */
150 static long long osnoise_write_ll_config(char *rel_path, long long value)
151 {
152         char buffer[BUFF_U64_STR_SIZE];
153         long long retval;
154
155         snprintf(buffer, sizeof(buffer), "%lld\n", value);
156
157         debug_msg("setting %s to %lld\n", rel_path, value);
158
159         retval = tracefs_instance_file_write(NULL, rel_path, buffer);
160         return retval;
161 }
162
163 /*
164  * osnoise_get_runtime - return the original "osnoise/runtime_us" value
165  *
166  * It also saves the value to be restored.
167  */
168 unsigned long long osnoise_get_runtime(struct osnoise_context *context)
169 {
170         long long runtime_us;
171
172         if (context->runtime_us != OSNOISE_TIME_INIT_VAL)
173                 return context->runtime_us;
174
175         if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL)
176                 return context->orig_runtime_us;
177
178         runtime_us = osnoise_read_ll_config("osnoise/runtime_us");
179         if (runtime_us < 0)
180                 goto out_err;
181
182         context->orig_runtime_us = runtime_us;
183         return runtime_us;
184
185 out_err:
186         return OSNOISE_TIME_INIT_VAL;
187 }
188
189 /*
190  * osnoise_get_period - return the original "osnoise/period_us" value
191  *
192  * It also saves the value to be restored.
193  */
194 unsigned long long osnoise_get_period(struct osnoise_context *context)
195 {
196         long long period_us;
197
198         if (context->period_us != OSNOISE_TIME_INIT_VAL)
199                 return context->period_us;
200
201         if (context->orig_period_us != OSNOISE_TIME_INIT_VAL)
202                 return context->orig_period_us;
203
204         period_us = osnoise_read_ll_config("osnoise/period_us");
205         if (period_us < 0)
206                 goto out_err;
207
208         context->orig_period_us = period_us;
209         return period_us;
210
211 out_err:
212         return OSNOISE_TIME_INIT_VAL;
213 }
214
215 static int __osnoise_write_runtime(struct osnoise_context *context,
216                                    unsigned long long runtime)
217 {
218         int retval;
219
220         if (context->orig_runtime_us == OSNOISE_TIME_INIT_VAL)
221                 return -1;
222
223         retval = osnoise_write_ll_config("osnoise/runtime_us", runtime);
224         if (retval < 0)
225                 return -1;
226
227         context->runtime_us = runtime;
228         return 0;
229 }
230
231 static int __osnoise_write_period(struct osnoise_context *context,
232                                   unsigned long long period)
233 {
234         int retval;
235
236         if (context->orig_period_us == OSNOISE_TIME_INIT_VAL)
237                 return -1;
238
239         retval = osnoise_write_ll_config("osnoise/period_us", period);
240         if (retval < 0)
241                 return -1;
242
243         context->period_us = period;
244         return 0;
245 }
246
247 /*
248  * osnoise_set_runtime_period - set osnoise runtime and period
249  *
250  * Osnoise's runtime and period are related as runtime <= period.
251  * Thus, this function saves the original values, and then tries
252  * to set the runtime and period if they are != 0.
253  */
254 int osnoise_set_runtime_period(struct osnoise_context *context,
255                                unsigned long long runtime,
256                                unsigned long long period)
257 {
258         unsigned long long curr_runtime_us;
259         unsigned long long curr_period_us;
260         int retval;
261
262         if (!period && !runtime)
263                 return 0;
264
265         curr_runtime_us = osnoise_get_runtime(context);
266         curr_period_us = osnoise_get_period(context);
267
268         /* error getting any value? */
269         if (curr_period_us == OSNOISE_TIME_INIT_VAL || curr_runtime_us == OSNOISE_TIME_INIT_VAL)
270                 return -1;
271
272         if (!period) {
273                 if (runtime > curr_period_us)
274                         return -1;
275                 return __osnoise_write_runtime(context, runtime);
276         } else if (!runtime) {
277                 if (period < curr_runtime_us)
278                         return -1;
279                 return __osnoise_write_period(context, period);
280         }
281
282         if (runtime > curr_period_us) {
283                 retval = __osnoise_write_period(context, period);
284                 if (retval)
285                         return -1;
286                 retval = __osnoise_write_runtime(context, runtime);
287                 if (retval)
288                         return -1;
289         } else {
290                 retval = __osnoise_write_runtime(context, runtime);
291                 if (retval)
292                         return -1;
293                 retval = __osnoise_write_period(context, period);
294                 if (retval)
295                         return -1;
296         }
297
298         return 0;
299 }
300
301 /*
302  * osnoise_restore_runtime_period - restore the original runtime and period
303  */
304 void osnoise_restore_runtime_period(struct osnoise_context *context)
305 {
306         unsigned long long orig_runtime = context->orig_runtime_us;
307         unsigned long long orig_period = context->orig_period_us;
308         unsigned long long curr_runtime = context->runtime_us;
309         unsigned long long curr_period = context->period_us;
310         int retval;
311
312         if ((orig_runtime == OSNOISE_TIME_INIT_VAL) && (orig_period == OSNOISE_TIME_INIT_VAL))
313                 return;
314
315         if ((orig_period == curr_period) && (orig_runtime == curr_runtime))
316                 goto out_done;
317
318         retval = osnoise_set_runtime_period(context, orig_runtime, orig_period);
319         if (retval)
320                 err_msg("Could not restore original osnoise runtime/period\n");
321
322 out_done:
323         context->runtime_us = OSNOISE_TIME_INIT_VAL;
324         context->period_us = OSNOISE_TIME_INIT_VAL;
325 }
326
327 /*
328  * osnoise_put_runtime_period - restore original values and cleanup data
329  */
330 void osnoise_put_runtime_period(struct osnoise_context *context)
331 {
332         osnoise_restore_runtime_period(context);
333
334         if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL)
335                 context->orig_runtime_us = OSNOISE_TIME_INIT_VAL;
336
337         if (context->orig_period_us != OSNOISE_TIME_INIT_VAL)
338                 context->orig_period_us = OSNOISE_TIME_INIT_VAL;
339 }
340
341 /*
342  * osnoise_get_timerlat_period_us - read and save the original "timerlat_period_us"
343  */
344 static long long
345 osnoise_get_timerlat_period_us(struct osnoise_context *context)
346 {
347         long long timerlat_period_us;
348
349         if (context->timerlat_period_us != OSNOISE_TIME_INIT_VAL)
350                 return context->timerlat_period_us;
351
352         if (context->orig_timerlat_period_us != OSNOISE_TIME_INIT_VAL)
353                 return context->orig_timerlat_period_us;
354
355         timerlat_period_us = osnoise_read_ll_config("osnoise/timerlat_period_us");
356         if (timerlat_period_us < 0)
357                 goto out_err;
358
359         context->orig_timerlat_period_us = timerlat_period_us;
360         return timerlat_period_us;
361
362 out_err:
363         return OSNOISE_TIME_INIT_VAL;
364 }
365
366 /*
367  * osnoise_set_timerlat_period_us - set "timerlat_period_us"
368  */
369 int osnoise_set_timerlat_period_us(struct osnoise_context *context, long long timerlat_period_us)
370 {
371         long long curr_timerlat_period_us = osnoise_get_timerlat_period_us(context);
372         int retval;
373
374         if (curr_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
375                 return -1;
376
377         retval = osnoise_write_ll_config("osnoise/timerlat_period_us", timerlat_period_us);
378         if (retval < 0)
379                 return -1;
380
381         context->timerlat_period_us = timerlat_period_us;
382
383         return 0;
384 }
385
386 /*
387  * osnoise_restore_timerlat_period_us - restore "timerlat_period_us"
388  */
389 void osnoise_restore_timerlat_period_us(struct osnoise_context *context)
390 {
391         int retval;
392
393         if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
394                 return;
395
396         if (context->orig_timerlat_period_us == context->timerlat_period_us)
397                 goto out_done;
398
399         retval = osnoise_write_ll_config("osnoise/timerlat_period_us", context->orig_timerlat_period_us);
400         if (retval < 0)
401                 err_msg("Could not restore original osnoise timerlat_period_us\n");
402
403 out_done:
404         context->timerlat_period_us = OSNOISE_TIME_INIT_VAL;
405 }
406
407 /*
408  * osnoise_put_timerlat_period_us - restore original values and cleanup data
409  */
410 void osnoise_put_timerlat_period_us(struct osnoise_context *context)
411 {
412         osnoise_restore_timerlat_period_us(context);
413
414         if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
415                 return;
416
417         context->orig_timerlat_period_us = OSNOISE_TIME_INIT_VAL;
418 }
419
420 /*
421  * osnoise_get_stop_us - read and save the original "stop_tracing_us"
422  */
423 static long long
424 osnoise_get_stop_us(struct osnoise_context *context)
425 {
426         long long stop_us;
427
428         if (context->stop_us != OSNOISE_OPTION_INIT_VAL)
429                 return context->stop_us;
430
431         if (context->orig_stop_us != OSNOISE_OPTION_INIT_VAL)
432                 return context->orig_stop_us;
433
434         stop_us = osnoise_read_ll_config("osnoise/stop_tracing_us");
435         if (stop_us < 0)
436                 goto out_err;
437
438         context->orig_stop_us = stop_us;
439         return stop_us;
440
441 out_err:
442         return OSNOISE_OPTION_INIT_VAL;
443 }
444
445 /*
446  * osnoise_set_stop_us - set "stop_tracing_us"
447  */
448 int osnoise_set_stop_us(struct osnoise_context *context, long long stop_us)
449 {
450         long long curr_stop_us = osnoise_get_stop_us(context);
451         int retval;
452
453         if (curr_stop_us == OSNOISE_OPTION_INIT_VAL)
454                 return -1;
455
456         retval = osnoise_write_ll_config("osnoise/stop_tracing_us", stop_us);
457         if (retval < 0)
458                 return -1;
459
460         context->stop_us = stop_us;
461
462         return 0;
463 }
464
465 /*
466  * osnoise_restore_stop_us - restore the original "stop_tracing_us"
467  */
468 void osnoise_restore_stop_us(struct osnoise_context *context)
469 {
470         int retval;
471
472         if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL)
473                 return;
474
475         if (context->orig_stop_us == context->stop_us)
476                 goto out_done;
477
478         retval = osnoise_write_ll_config("osnoise/stop_tracing_us", context->orig_stop_us);
479         if (retval < 0)
480                 err_msg("Could not restore original osnoise stop_us\n");
481
482 out_done:
483         context->stop_us = OSNOISE_OPTION_INIT_VAL;
484 }
485
486 /*
487  * osnoise_put_stop_us - restore original values and cleanup data
488  */
489 void osnoise_put_stop_us(struct osnoise_context *context)
490 {
491         osnoise_restore_stop_us(context);
492
493         if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL)
494                 return;
495
496         context->orig_stop_us = OSNOISE_OPTION_INIT_VAL;
497 }
498
499 /*
500  * osnoise_get_stop_total_us - read and save the original "stop_tracing_total_us"
501  */
502 static long long
503 osnoise_get_stop_total_us(struct osnoise_context *context)
504 {
505         long long stop_total_us;
506
507         if (context->stop_total_us != OSNOISE_OPTION_INIT_VAL)
508                 return context->stop_total_us;
509
510         if (context->orig_stop_total_us != OSNOISE_OPTION_INIT_VAL)
511                 return context->orig_stop_total_us;
512
513         stop_total_us = osnoise_read_ll_config("osnoise/stop_tracing_total_us");
514         if (stop_total_us < 0)
515                 goto out_err;
516
517         context->orig_stop_total_us = stop_total_us;
518         return stop_total_us;
519
520 out_err:
521         return OSNOISE_OPTION_INIT_VAL;
522 }
523
524 /*
525  * osnoise_set_stop_total_us - set "stop_tracing_total_us"
526  */
527 int osnoise_set_stop_total_us(struct osnoise_context *context, long long stop_total_us)
528 {
529         long long curr_stop_total_us = osnoise_get_stop_total_us(context);
530         int retval;
531
532         if (curr_stop_total_us == OSNOISE_OPTION_INIT_VAL)
533                 return -1;
534
535         retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", stop_total_us);
536         if (retval < 0)
537                 return -1;
538
539         context->stop_total_us = stop_total_us;
540
541         return 0;
542 }
543
544 /*
545  * osnoise_restore_stop_total_us - restore the original "stop_tracing_total_us"
546  */
547 void osnoise_restore_stop_total_us(struct osnoise_context *context)
548 {
549         int retval;
550
551         if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL)
552                 return;
553
554         if (context->orig_stop_total_us == context->stop_total_us)
555                 goto out_done;
556
557         retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us",
558                         context->orig_stop_total_us);
559         if (retval < 0)
560                 err_msg("Could not restore original osnoise stop_total_us\n");
561
562 out_done:
563         context->stop_total_us = OSNOISE_OPTION_INIT_VAL;
564 }
565
566 /*
567  * osnoise_put_stop_total_us - restore original values and cleanup data
568  */
569 void osnoise_put_stop_total_us(struct osnoise_context *context)
570 {
571         osnoise_restore_stop_total_us(context);
572
573         if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL)
574                 return;
575
576         context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL;
577 }
578
579 /*
580  * osnoise_get_print_stack - read and save the original "print_stack"
581  */
582 static long long
583 osnoise_get_print_stack(struct osnoise_context *context)
584 {
585         long long print_stack;
586
587         if (context->print_stack != OSNOISE_OPTION_INIT_VAL)
588                 return context->print_stack;
589
590         if (context->orig_print_stack != OSNOISE_OPTION_INIT_VAL)
591                 return context->orig_print_stack;
592
593         print_stack = osnoise_read_ll_config("osnoise/print_stack");
594         if (print_stack < 0)
595                 goto out_err;
596
597         context->orig_print_stack = print_stack;
598         return print_stack;
599
600 out_err:
601         return OSNOISE_OPTION_INIT_VAL;
602 }
603
604 /*
605  * osnoise_set_print_stack - set "print_stack"
606  */
607 int osnoise_set_print_stack(struct osnoise_context *context, long long print_stack)
608 {
609         long long curr_print_stack = osnoise_get_print_stack(context);
610         int retval;
611
612         if (curr_print_stack == OSNOISE_OPTION_INIT_VAL)
613                 return -1;
614
615         retval = osnoise_write_ll_config("osnoise/print_stack", print_stack);
616         if (retval < 0)
617                 return -1;
618
619         context->print_stack = print_stack;
620
621         return 0;
622 }
623
624 /*
625  * osnoise_restore_print_stack - restore the original "print_stack"
626  */
627 void osnoise_restore_print_stack(struct osnoise_context *context)
628 {
629         int retval;
630
631         if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL)
632                 return;
633
634         if (context->orig_print_stack == context->print_stack)
635                 goto out_done;
636
637         retval = osnoise_write_ll_config("osnoise/print_stack", context->orig_print_stack);
638         if (retval < 0)
639                 err_msg("Could not restore original osnoise print_stack\n");
640
641 out_done:
642         context->print_stack = OSNOISE_OPTION_INIT_VAL;
643 }
644
645 /*
646  * osnoise_put_print_stack - restore original values and cleanup data
647  */
648 void osnoise_put_print_stack(struct osnoise_context *context)
649 {
650         osnoise_restore_print_stack(context);
651
652         if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL)
653                 return;
654
655         context->orig_print_stack = OSNOISE_OPTION_INIT_VAL;
656 }
657
658 /*
659  * enable_osnoise - enable osnoise tracer in the trace_instance
660  */
661 int enable_osnoise(struct trace_instance *trace)
662 {
663         return enable_tracer_by_name(trace->inst, "osnoise");
664 }
665
666 /*
667  * enable_timerlat - enable timerlat tracer in the trace_instance
668  */
669 int enable_timerlat(struct trace_instance *trace)
670 {
671         return enable_tracer_by_name(trace->inst, "timerlat");
672 }
673
674 enum {
675         FLAG_CONTEXT_NEWLY_CREATED      = (1 << 0),
676         FLAG_CONTEXT_DELETED            = (1 << 1),
677 };
678
679 /*
680  * osnoise_get_context - increase the usage of a context and return it
681  */
682 int osnoise_get_context(struct osnoise_context *context)
683 {
684         int ret;
685
686         if (context->flags & FLAG_CONTEXT_DELETED) {
687                 ret = -1;
688         } else {
689                 context->ref++;
690                 ret = 0;
691         }
692
693         return ret;
694 }
695
696 /*
697  * osnoise_context_alloc - alloc an osnoise_context
698  *
699  * The osnoise context contains the information of the "osnoise/" configs.
700  * It is used to set and restore the config.
701  */
702 struct osnoise_context *osnoise_context_alloc(void)
703 {
704         struct osnoise_context *context;
705
706         context = calloc(1, sizeof(*context));
707         if (!context)
708                 return NULL;
709
710         context->orig_stop_us           = OSNOISE_OPTION_INIT_VAL;
711         context->stop_us                = OSNOISE_OPTION_INIT_VAL;
712
713         context->orig_stop_total_us     = OSNOISE_OPTION_INIT_VAL;
714         context->stop_total_us          = OSNOISE_OPTION_INIT_VAL;
715
716         context->orig_print_stack       = OSNOISE_OPTION_INIT_VAL;
717         context->print_stack            = OSNOISE_OPTION_INIT_VAL;
718
719         osnoise_get_context(context);
720
721         return context;
722 }
723
724 /*
725  * osnoise_put_context - put the osnoise_put_context
726  *
727  * If there is no other user for the context, the original data
728  * is restored.
729  */
730 void osnoise_put_context(struct osnoise_context *context)
731 {
732         if (--context->ref < 1)
733                 context->flags |= FLAG_CONTEXT_DELETED;
734
735         if (!(context->flags & FLAG_CONTEXT_DELETED))
736                 return;
737
738         osnoise_put_cpus(context);
739         osnoise_put_runtime_period(context);
740         osnoise_put_stop_us(context);
741         osnoise_put_stop_total_us(context);
742         osnoise_put_timerlat_period_us(context);
743         osnoise_put_print_stack(context);
744
745         free(context);
746 }
747
748 /*
749  * osnoise_destroy_tool - disable trace, restore configs and free data
750  */
751 void osnoise_destroy_tool(struct osnoise_tool *top)
752 {
753         trace_instance_destroy(&top->trace);
754
755         if (top->context)
756                 osnoise_put_context(top->context);
757
758         free(top);
759 }
760
761 /*
762  * osnoise_init_tool - init an osnoise tool
763  *
764  * It allocs data, create a context to store data and
765  * creates a new trace instance for the tool.
766  */
767 struct osnoise_tool *osnoise_init_tool(char *tool_name)
768 {
769         struct osnoise_tool *top;
770         int retval;
771
772         top = calloc(1, sizeof(*top));
773         if (!top)
774                 return NULL;
775
776         top->context = osnoise_context_alloc();
777         if (!top->context)
778                 goto out_err;
779
780         retval = trace_instance_init(&top->trace, tool_name);
781         if (retval)
782                 goto out_err;
783
784         return top;
785 out_err:
786         osnoise_destroy_tool(top);
787         return NULL;
788 }
789
790 /*
791  * osnoise_init_trace_tool - init a tracer instance to trace osnoise events
792  */
793 struct osnoise_tool *osnoise_init_trace_tool(char *tracer)
794 {
795         struct osnoise_tool *trace;
796         int retval;
797
798         trace = osnoise_init_tool("osnoise_trace");
799         if (!trace)
800                 return NULL;
801
802         retval = tracefs_event_enable(trace->trace.inst, "osnoise", NULL);
803         if (retval < 0 && !errno) {
804                 err_msg("Could not find osnoise events\n");
805                 goto out_err;
806         }
807
808         retval = enable_tracer_by_name(trace->trace.inst, tracer);
809         if (retval) {
810                 err_msg("Could not enable osnoiser tracer for tracing\n");
811                 goto out_err;
812         }
813
814         return trace;
815 out_err:
816         osnoise_destroy_tool(trace);
817         return NULL;
818 }
819
820 static void osnoise_usage(void)
821 {
822         int i;
823
824         static const char *msg[] = {
825                 "",
826                 "osnoise version " VERSION,
827                 "",
828                 "  usage: [rtla] osnoise [MODE] ...",
829                 "",
830                 "  modes:",
831                 "     top   - prints the summary from osnoise tracer",
832                 "     hist  - prints a histogram of osnoise samples",
833                 "",
834                 "if no MODE is given, the top mode is called, passing the arguments",
835                 NULL,
836         };
837
838         for (i = 0; msg[i]; i++)
839                 fprintf(stderr, "%s\n", msg[i]);
840         exit(1);
841 }
842
843 int osnoise_main(int argc, char *argv[])
844 {
845         if (argc == 0)
846                 goto usage;
847
848         /*
849          * if osnoise was called without any argument, run the
850          * default cmdline.
851          */
852         if (argc == 1) {
853                 osnoise_top_main(argc, argv);
854                 exit(0);
855         }
856
857         if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
858                 osnoise_usage();
859                 exit(0);
860         } else if (strncmp(argv[1], "-", 1) == 0) {
861                 /* the user skipped the tool, call the default one */
862                 osnoise_top_main(argc, argv);
863                 exit(0);
864         } else if (strcmp(argv[1], "top") == 0) {
865                 osnoise_top_main(argc-1, &argv[1]);
866                 exit(0);
867         } else if (strcmp(argv[1], "hist") == 0) {
868                 osnoise_hist_main(argc-1, &argv[1]);
869                 exit(0);
870         }
871
872 usage:
873         osnoise_usage();
874         exit(1);
875 }