]> www.infradead.org Git - users/willy/xarray.git/commitdiff
of: unittest: Add a case to test if API of_irq_parse_raw() leaks refcount
authorZijun Hu <quic_zijuhu@quicinc.com>
Sun, 9 Feb 2025 12:58:56 +0000 (20:58 +0800)
committerRob Herring (Arm) <robh@kernel.org>
Tue, 25 Feb 2025 13:16:50 +0000 (07:16 -0600)
To test if of_irq_parse_raw(), invoked by of_irq_parse_one(), will leak
refcount of interrupt combo node consisting of controller and nexus.

Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-3-93e3a2659aa7@quicinc.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
drivers/of/unittest-data/tests-interrupts.dtsi
drivers/of/unittest.c

index 7c9f31cc131bae79ed81a1654cfc564e9c85bf9d..4ccb54f91c3068c0857f461fea0cf465aa0e2633 100644 (file)
                                interrupt-map = <0x5000 1 2 &test_intc0 15>;
                        };
 
+                       test_intc_intmap0: intc-intmap0 {
+                               #interrupt-cells = <1>;
+                               #address-cells = <1>;
+                               interrupt-controller;
+                               interrupt-map = <0x6000 1 &test_intc_intmap0 0x7000 2>;
+                       };
+
                        interrupts0 {
                                interrupt-parent = <&test_intc0>;
                                interrupts = <1>, <2>, <3>, <4>;
                                interrupts = <1>, <2>, <3>, <4>;
                        };
 
+                       interrupts2 {
+                               reg = <0x6000 0x100>;
+                               interrupt-parent = <&test_intc_intmap0>;
+                               interrupts = <1>;
+                       };
+
                        interrupts-extended0 {
                                reg = <0x5000 0x100>;
                                /*
index 48aec4695fff647226697fefcae696adaa307480..64d301893af7b861cf3e3c25d10f943dfd92bc03 100644 (file)
@@ -1659,6 +1659,7 @@ static void __init of_unittest_irq_refcount(void)
 {
        struct of_phandle_args args;
        struct device_node *intc0, *int_ext0;
+       struct device_node *int2, *intc_intmap0;
        unsigned int ref_c0, ref_c1, ref_c2;
        int rc;
        bool passed;
@@ -1668,7 +1669,9 @@ static void __init of_unittest_irq_refcount(void)
 
        intc0 = of_find_node_by_path("/testcase-data/interrupts/intc0");
        int_ext0 = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
-       if (!intc0 || !int_ext0) {
+       intc_intmap0 = of_find_node_by_path("/testcase-data/interrupts/intc-intmap0");
+       int2 = of_find_node_by_path("/testcase-data/interrupts/interrupts2");
+       if (!intc0 || !int_ext0 || !intc_intmap0 || !int2) {
                pr_err("missing testcase data\n");
                goto out;
        }
@@ -1690,7 +1693,26 @@ static void __init of_unittest_irq_refcount(void)
        unittest(passed, "IRQ refcount case #1 failed, original(%u) expected(%u) got(%u)\n",
                 ref_c0, ref_c1, ref_c2);
 
+       /* Test refcount for API of_irq_parse_raw() */
+       passed = true;
+       ref_c0 = OF_KREF_READ(intc_intmap0);
+       ref_c1 = ref_c0 + 1;
+       memset(&args, 0, sizeof(args));
+       rc = of_irq_parse_one(int2, 0, &args);
+       ref_c2 = OF_KREF_READ(intc_intmap0);
+       of_node_put(args.np);
+
+       passed &= !rc;
+       passed &= (args.np == intc_intmap0);
+       passed &= (args.args_count == 1);
+       passed &= (args.args[0] == 2);
+       passed &= (ref_c1 == ref_c2);
+       unittest(passed, "IRQ refcount case #2 failed, original(%u) expected(%u) got(%u)\n",
+                ref_c0, ref_c1, ref_c2);
+
 out:
+       of_node_put(int2);
+       of_node_put(intc_intmap0);
        of_node_put(int_ext0);
        of_node_put(intc0);
 }