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