1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// SPDX-License-Identifier: GPL-2.0
/*
* KUnit test for refcounted interrupt enable/disables.
*/
#include <kunit/test.h>
#include <linux/interrupt_rc.h>
#define TEST_IRQ_ON() KUNIT_EXPECT_FALSE(test, irqs_disabled())
#define TEST_IRQ_OFF() KUNIT_EXPECT_TRUE(test, irqs_disabled())
/* ===== Test cases ===== */
static void test_single_irq_change(struct kunit *test)
{
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
}
static void test_nested_irq_change(struct kunit *test)
{
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_ON();
}
static void test_multiple_irq_change(struct kunit *test)
{
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_ON();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_ON();
}
static void test_max_nesting_irq_change(struct kunit *test)
{
for (int i = 0; i < __IRQ_MASK(HARDIRQ_DISABLE_BITS); i++) {
local_interrupt_disable();
TEST_IRQ_OFF();
}
for (int i = 0; i < __IRQ_MASK(HARDIRQ_DISABLE_BITS); i++) {
TEST_IRQ_OFF();
local_interrupt_enable();
}
TEST_IRQ_ON();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_ON();
}
static void test_irq_save(struct kunit *test)
{
unsigned long flags;
local_irq_save(flags);
TEST_IRQ_OFF();
local_interrupt_disable();
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_OFF();
local_irq_restore(flags);
TEST_IRQ_ON();
local_interrupt_disable();
TEST_IRQ_OFF();
local_irq_save(flags);
TEST_IRQ_OFF();
local_irq_restore(flags);
TEST_IRQ_OFF();
local_interrupt_enable();
TEST_IRQ_ON();
}
static struct kunit_case test_cases[] = {
KUNIT_CASE(test_single_irq_change),
KUNIT_CASE(test_nested_irq_change),
KUNIT_CASE(test_multiple_irq_change),
KUNIT_CASE(test_max_nesting_irq_change),
KUNIT_CASE(test_irq_save),
{},
};
/* init and exit are the same. */
static int test_init(struct kunit *test)
{
TEST_IRQ_ON();
return 0;
}
static void test_exit(struct kunit *test)
{
TEST_IRQ_ON();
}
static struct kunit_suite refcount_interrupt_test_suite = {
.name = "refcount_interrupt",
.test_cases = test_cases,
.init = test_init,
.exit = test_exit,
};
kunit_test_suite(refcount_interrupt_test_suite);
MODULE_AUTHOR("Lyude Paul <lyude@redhat.com>");
MODULE_DESCRIPTION("Refcounted interrupt unit test suite");
MODULE_LICENSE("GPL");
|