aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorZijun Hu <quic_zijuhu@quicinc.com>2025-02-09 20:58:56 +0800
committerRob Herring (Arm) <robh@kernel.org>2025-02-25 07:16:50 -0600
commitf8647991e07f42d1525c63cfa5a021b3869ef630 (patch)
tree1453143921b831ab7619fc8fa105a6a6132f2104
parentof/irq: Fix device node refcount leakage in API of_irq_parse_one() (diff)
downloadwireguard-linux-f8647991e07f42d1525c63cfa5a021b3869ef630.tar.xz
wireguard-linux-f8647991e07f42d1525c63cfa5a021b3869ef630.zip
of: unittest: Add a case to test if API of_irq_parse_raw() leaks refcount
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>
-rw-r--r--drivers/of/unittest-data/tests-interrupts.dtsi13
-rw-r--r--drivers/of/unittest.c24
2 files changed, 36 insertions, 1 deletions
diff --git a/drivers/of/unittest-data/tests-interrupts.dtsi b/drivers/of/unittest-data/tests-interrupts.dtsi
index 7c9f31cc131b..4ccb54f91c30 100644
--- a/drivers/of/unittest-data/tests-interrupts.dtsi
+++ b/drivers/of/unittest-data/tests-interrupts.dtsi
@@ -50,6 +50,13 @@
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>;
@@ -60,6 +67,12 @@
interrupts = <1>, <2>, <3>, <4>;
};
+ interrupts2 {
+ reg = <0x6000 0x100>;
+ interrupt-parent = <&test_intc_intmap0>;
+ interrupts = <1>;
+ };
+
interrupts-extended0 {
reg = <0x5000 0x100>;
/*
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 48aec4695fff..64d301893af7 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -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);
}