genirq/timings: Add selftest for irqs circular buffer
authorDaniel Lezcano <daniel.lezcano@linaro.org>
Mon, 27 May 2019 20:55:20 +0000 (22:55 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 12 Jun 2019 08:47:05 +0000 (10:47 +0200)
After testing the per cpu interrupt circular event, make sure the per
interrupt circular buffer usage is correct.

Add tests to validate the interrupt circular buffer.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: andriy.shevchenko@linux.intel.com
Link: https://lkml.kernel.org/r/20190527205521.12091-8-daniel.lezcano@linaro.org
kernel/irq/timings.c

index 95b63bd..5b13c22 100644 (file)
@@ -629,6 +629,141 @@ int irq_timings_alloc(int irq)
 }
 
 #ifdef CONFIG_TEST_IRQ_TIMINGS
+struct timings_intervals {
+       u64 *intervals;
+       size_t count;
+};
+
+/*
+ * Intervals are given in nanosecond base
+ */
+static u64 intervals0[] __initdata = {
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000, 500000,
+       10000, 50000, 200000,
+};
+
+static u64 intervals1[] __initdata = {
+       223947000, 1240000, 1384000, 1386000, 1386000,
+       217416000, 1236000, 1384000, 1386000, 1387000,
+       214719000, 1241000, 1386000, 1387000, 1384000,
+       213696000, 1234000, 1384000, 1386000, 1388000,
+       219904000, 1240000, 1385000, 1389000, 1385000,
+       212240000, 1240000, 1386000, 1386000, 1386000,
+       214415000, 1236000, 1384000, 1386000, 1387000,
+       214276000, 1234000,
+};
+
+static u64 intervals2[] __initdata = {
+       4000, 3000, 5000, 100000,
+       3000, 3000, 5000, 117000,
+       4000, 4000, 5000, 112000,
+       4000, 3000, 4000, 110000,
+       3000, 5000, 3000, 117000,
+       4000, 4000, 5000, 112000,
+       4000, 3000, 4000, 110000,
+       3000, 4000, 5000, 112000,
+       4000,
+};
+
+static u64 intervals3[] __initdata = {
+       1385000, 212240000, 1240000,
+       1386000, 214415000, 1236000,
+       1384000, 214276000, 1234000,
+       1386000, 214415000, 1236000,
+       1385000, 212240000, 1240000,
+       1386000, 214415000, 1236000,
+       1384000, 214276000, 1234000,
+       1386000, 214415000, 1236000,
+       1385000, 212240000, 1240000,
+};
+
+static u64 intervals4[] __initdata = {
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000, 50000, 10000, 50000,
+       10000,
+};
+
+static struct timings_intervals tis[] __initdata = {
+       { intervals0, ARRAY_SIZE(intervals0) },
+       { intervals1, ARRAY_SIZE(intervals1) },
+       { intervals2, ARRAY_SIZE(intervals2) },
+       { intervals3, ARRAY_SIZE(intervals3) },
+       { intervals4, ARRAY_SIZE(intervals4) },
+};
+
+static int __init irq_timings_test_irqs(struct timings_intervals *ti)
+{
+       struct irqt_stat __percpu *s;
+       struct irqt_stat *irqs;
+       int i, index, ret, irq = 0xACE5;
+
+       ret = irq_timings_alloc(irq);
+       if (ret) {
+               pr_err("Failed to allocate irq timings\n");
+               return ret;
+       }
+
+       s = idr_find(&irqt_stats, irq);
+       if (!s) {
+               ret = -EIDRM;
+               goto out;
+       }
+
+       irqs = this_cpu_ptr(s);
+
+       for (i = 0; i < ti->count; i++) {
+
+               index = irq_timings_interval_index(ti->intervals[i]);
+               pr_debug("%d: interval=%llu ema_index=%d\n",
+                        i, ti->intervals[i], index);
+
+               __irq_timings_store(irq, irqs, ti->intervals[i]);
+               if (irqs->circ_timings[i & IRQ_TIMINGS_MASK] != index) {
+                       pr_err("Failed to store in the circular buffer\n");
+                       goto out;
+               }
+       }
+
+       if (irqs->count != ti->count) {
+               pr_err("Count differs\n");
+               goto out;
+       }
+
+       ret = 0;
+out:
+       irq_timings_free(irq);
+
+       return ret;
+}
+
+static int __init irq_timings_irqs_selftest(void)
+{
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(tis); i++) {
+               pr_info("---> Injecting intervals number #%d (count=%zd)\n",
+                       i, tis[i].count);
+               ret = irq_timings_test_irqs(&tis[i]);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
 static int __init irq_timings_test_irqts(struct irq_timings *irqts,
                                         unsigned count)
 {
@@ -736,7 +871,11 @@ static int __init irq_timings_selftest(void)
        }
 
        ret = irq_timings_irqts_selftest();
+       if (ret)
+               goto out;
 
+       ret = irq_timings_irqs_selftest();
+out:
        pr_info("---------- selftest end with %s -----------\n",
                ret ? "failure" : "success");