timings.c (23aa3b9a6b7d5029c1f124426bc5ba4430dcc29c) timings.c (6aed82de719b424bd5548aa4179e95f34fd779ab)
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
3#define pr_fmt(fmt) "irq_timings: " fmt
3
4#include <linux/kernel.h>
5#include <linux/percpu.h>
6#include <linux/slab.h>
7#include <linux/static_key.h>
4
5#include <linux/kernel.h>
6#include <linux/percpu.h>
7#include <linux/slab.h>
8#include <linux/static_key.h>
9#include <linux/init.h>
8#include <linux/interrupt.h>
9#include <linux/idr.h>
10#include <linux/irq.h>
11#include <linux/math64.h>
12#include <linux/log2.h>
13
14#include <trace/events/irq.h>
15

--- 604 unchanged lines hidden (view full) ---

620
621 if (id < 0) {
622 free_percpu(s);
623 return id;
624 }
625
626 return 0;
627}
10#include <linux/interrupt.h>
11#include <linux/idr.h>
12#include <linux/irq.h>
13#include <linux/math64.h>
14#include <linux/log2.h>
15
16#include <trace/events/irq.h>
17

--- 604 unchanged lines hidden (view full) ---

622
623 if (id < 0) {
624 free_percpu(s);
625 return id;
626 }
627
628 return 0;
629}
630
631#ifdef CONFIG_TEST_IRQ_TIMINGS
632static int __init irq_timings_test_irqts(struct irq_timings *irqts,
633 unsigned count)
634{
635 int start = count >= IRQ_TIMINGS_SIZE ? count - IRQ_TIMINGS_SIZE : 0;
636 int i, irq, oirq = 0xBEEF;
637 u64 ots = 0xDEAD, ts;
638
639 /*
640 * Fill the circular buffer by using the dedicated function.
641 */
642 for (i = 0; i < count; i++) {
643 pr_debug("%d: index=%d, ts=%llX irq=%X\n",
644 i, i & IRQ_TIMINGS_MASK, ots + i, oirq + i);
645
646 irq_timings_push(ots + i, oirq + i);
647 }
648
649 /*
650 * Compute the first elements values after the index wrapped
651 * up or not.
652 */
653 ots += start;
654 oirq += start;
655
656 /*
657 * Test the circular buffer count is correct.
658 */
659 pr_debug("---> Checking timings array count (%d) is right\n", count);
660 if (WARN_ON(irqts->count != count))
661 return -EINVAL;
662
663 /*
664 * Test the macro allowing to browse all the irqts.
665 */
666 pr_debug("---> Checking the for_each_irqts() macro\n");
667 for_each_irqts(i, irqts) {
668
669 irq = irq_timing_decode(irqts->values[i], &ts);
670
671 pr_debug("index=%d, ts=%llX / %llX, irq=%X / %X\n",
672 i, ts, ots, irq, oirq);
673
674 if (WARN_ON(ts != ots || irq != oirq))
675 return -EINVAL;
676
677 ots++; oirq++;
678 }
679
680 /*
681 * The circular buffer should have be flushed when browsed
682 * with for_each_irqts
683 */
684 pr_debug("---> Checking timings array is empty after browsing it\n");
685 if (WARN_ON(irqts->count))
686 return -EINVAL;
687
688 return 0;
689}
690
691static int __init irq_timings_irqts_selftest(void)
692{
693 struct irq_timings *irqts = this_cpu_ptr(&irq_timings);
694 int i, ret;
695
696 /*
697 * Test the circular buffer with different number of
698 * elements. The purpose is to test at the limits (empty, half
699 * full, full, wrapped with the cursor at the boundaries,
700 * wrapped several times, etc ...
701 */
702 int count[] = { 0,
703 IRQ_TIMINGS_SIZE >> 1,
704 IRQ_TIMINGS_SIZE,
705 IRQ_TIMINGS_SIZE + (IRQ_TIMINGS_SIZE >> 1),
706 2 * IRQ_TIMINGS_SIZE,
707 (2 * IRQ_TIMINGS_SIZE) + 3,
708 };
709
710 for (i = 0; i < ARRAY_SIZE(count); i++) {
711
712 pr_info("---> Checking the timings with %d/%d values\n",
713 count[i], IRQ_TIMINGS_SIZE);
714
715 ret = irq_timings_test_irqts(irqts, count[i]);
716 if (ret)
717 break;
718 }
719
720 return ret;
721}
722
723static int __init irq_timings_selftest(void)
724{
725 int ret;
726
727 pr_info("------------------- selftest start -----------------\n");
728
729 /*
730 * At this point, we don't except any subsystem to use the irq
731 * timings but us, so it should not be enabled.
732 */
733 if (static_branch_unlikely(&irq_timing_enabled)) {
734 pr_warn("irq timings already initialized, skipping selftest\n");
735 return 0;
736 }
737
738 ret = irq_timings_irqts_selftest();
739
740 pr_info("---------- selftest end with %s -----------\n",
741 ret ? "failure" : "success");
742
743 return ret;
744}
745early_initcall(irq_timings_selftest);
746#endif