New kernels
Re: New kernels
Please add libata.force=noncq to the boot arguments.
setenv bootargs "root=/dev/<partition or disk> libata.force=noncq"
setenv bootargs "root=/dev/<partition or disk> libata.force=noncq"
Re: New kernels
Okay I tried that. I saw no change. It got stuck on sata as long as usual and failed to identify devices.
With device it ends up with kernel panic. With ramdisk it fails to locate depmod file then fails assign MAC for dummy0. Then it stalls.
It also messes up the sata registers as on reboot to a working kernel, like 5.12.0 here with Xenial, it gets delayed on sata for a short while but finally gets over it.
With device it ends up with kernel panic. With ramdisk it fails to locate depmod file then fails assign MAC for dummy0. Then it stalls.
It also messes up the sata registers as on reboot to a working kernel, like 5.12.0 here with Xenial, it gets delayed on sata for a short while but finally gets over it.
Re: New kernels
Thank you for testing!Hypex wrote: Fri Jun 28, 2024 8:19 pm Okay I tried that. I saw no change. It got stuck on sata as long as usual and failed to identify devices.
With device it ends up with kernel panic. With ramdisk it fails to locate depmod file then fails assign MAC for dummy0. Then it stalls.
It also messes up the sata registers as on reboot to a working kernel, like 5.12.0 here with Xenial, it gets delayed on sata for a short while but finally gets over it.
Re: New kernels
Do you mean the latest stable longterm kernel 5.10.218 for our X1000 and X5000?Hypex wrote: Thu Jun 27, 2024 7:20 pm I retested vmlinux-6.10-10 again. Twice. Got a kernel panic.
I then tested vmlinux-6.10-14. Acted exactly the same. Has trouble with sata.
Also the 5.10.288 LTS kernel has issues. It cannot reset. When it resets machine it just sits there.
The 5.10.288 doesn't exist.
I tested the kernel 5.10.218 today and the reboot (reset) works.
Re: New kernels
I'll try bisecting again ...
About bisecting:
About bisecting:
Git bisect is like a little wizard that walks you through recent commits, asks you if they are good or bad, and narrows down the broken commit.
Git bisect starts with the midpoint commit. The midpoint commit is between the initial good commit and the initial bad commit.
If the midpoint commit was good, you know the commit that introduced the change is between your midpoint and the initial bad commit.
If the midpoint commit was bad, you know the commit that introduced the change is between your midpoint and the initial good commit.
After that git bisect selects a new midpoint in the area where the commit was bad. And this is repeated over and over again till the bad commit has been found.
-
Code: Select all
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git b
-
Code: Select all
git bisect start
- (Good: Linux 6.10-rc2)
Code: Select all
git bisect good c3f38fa61af77b49866b006939479069cd451173
- (Bad: Linux 6.10-rc3)
Code: Select all
git bisect bad 83a7eefedc9b56fe7bfeff13b6c7356688ffa670
Output:Code: Select all
[d30d0e49da71de8df10bf3ff1b3de880653af562] Merge tag 'net-6.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
- git bisect bad
Output:Code: Select all
[411c0ea696cc4fcd14a32f2093c909e0c59c5dd7] Merge branch 'af_unix-fix-lockless-access-of-sk-sk_state-and-others-fields'
- git bisect good
Output:Code: Select all
Bisecting: 46 revisions left to test after this (roughly 6 steps) [71d7b52cc33bc3b6697cce8a0a5ac9032f372e47] Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
- git bisect bad
Output:Code: Select all
[45ce0314bf258bd387d92782d5393e7b84b0121f] Merge tag 'kvmarm-fixes-6.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
- git bisect good
Output:Code: Select all
Bisecting: 18 revisions left to test after this (roughly 4 steps) [4bf15b1c657d22d1d70173e43264e4606dfe75ff] selftests/futex: don't pass a const char* to asprintf(3)
- git bisect good
Output:Code: Select all
Bisecting: 8 revisions left to test after this (roughly 3 steps) [2ab79514109578fc4b6df90633d500cf281eb689] Merge tag 'cxl-fixes-6.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
- git bisect good
Output:Code: Select all
Bisecting: 4 revisions left to test after this (roughly 2 steps) [935df1bd40d43c4ee91838c42a20e9af751885cc] of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw()
- git bisect bad
Output:Code: Select all
Bisecting: 1 revision left to test after this (roughly 1 step) [84081a885394fc94055c24c727c99c321df6abac] dt-bindings: arm: sunxi: Fix incorrect '-' usage
- git bisect good
Output:Code: Select all
Bisecting: 0 revisions left to test after this (roughly 0 steps) [321e4fa68ce15660ec578bdec5cc9607635087cf] dt-bindings: arm: stm32: st,mlahb: Drop spurious "reg" property from example
- git bisect good
Output:We have another bad commit.Code: Select all
935df1bd40d43c4ee91838c42a20e9af751885cc is the first bad commit commit 935df1bd40d43c4ee91838c42a20e9af751885cc Author: Rob Herring (Arm) <[email protected]> Date: Wed May 29 14:59:20 2024 -0500 of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() Factor out the parsing of interrupt-map interrupt parent phandle and its arg cells to a separate function, of_irq_parse_imap_parent(), so that it can be used in other parsing scenarios (e.g. fw_devlink). There was a refcount leak on non-matching entries when iterating thru "interrupt-map" which is fixed. Tested-by: Marc Zyngier <[email protected]> Tested-by: Anup Patel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Rob Herring (Arm) <[email protected]> drivers/of/irq.c | 125 ++++++++++++++++++++++++++++-------------------- drivers/of/of_private.h | 3 ++ 2 files changed, 77 insertions(+), 51 deletions(-)
of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() (935df1bd40d43c4ee91838c42a20e9af751885cc) is the first bad commit.
Cheers,
Christian
Last edited by xeno74 on Sat Jun 29, 2024 2:00 pm, edited 11 times in total.
Re: New kernels
Oh sorry yes, I misspelt 218.

Oops.The 5.10.288 doesn't exist.
I tested it from Xenial. I selected to reboot from menu. It shuts down, the kernel closes itself and the machine resets. Then shortly after the monitor goes into standby and nothing else happens. It's similar to other issues I've seen on the X1000 where CFE stalls in reset routine for some reason.I tested the kernel 5.10.218 today and the reboot (reset) works.
Re: New kernels
We have another bad commit.
of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() (935df1bd40d43c4ee91838c42a20e9af751885cc) is the first bad commit.
We have to check, if this commit is really the first bad commit.
Compiling the kernel with the first bad commit ...
Result: ATA failed to IDENTIFY (I/O error) -> Correct result
Next step reverting the first bad commit and compiling again ...
Output:
Compiling the kernel with the reverted first bad commit ... Result: Kernel boots
of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() (935df1bd40d43c4ee91838c42a20e9af751885cc) is the first bad commit.
Code: Select all
935df1bd40d43c4ee91838c42a20e9af751885cc is the first bad commit
commit 935df1bd40d43c4ee91838c42a20e9af751885cc
Author: Rob Herring (Arm) <[email protected]>
Date: Wed May 29 14:59:20 2024 -0500
of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw()
Factor out the parsing of interrupt-map interrupt parent phandle and its
arg cells to a separate function, of_irq_parse_imap_parent(), so that it
can be used in other parsing scenarios (e.g. fw_devlink).
There was a refcount leak on non-matching entries when iterating thru
"interrupt-map" which is fixed.
Tested-by: Marc Zyngier <[email protected]>
Tested-by: Anup Patel <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Rob Herring (Arm) <[email protected]>
drivers/of/irq.c | 125 ++++++++++++++++++++++++++++--------------------
drivers/of/of_private.h | 3 ++
2 files changed, 77 insertions(+), 51 deletions(-)
Code: Select all
git checkout 935df1bd40d43c4ee91838c42a20e9af751885cc
Code: Select all
Note: switching to '935df1bd40d43c4ee91838c42a20e9af751885cc'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 935df1bd40d4 of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw()
Result: ATA failed to IDENTIFY (I/O error) -> Correct result
Next step reverting the first bad commit and compiling again ...
Code: Select all
git checkout 935df1bd40d43c4ee91838c42a20e9af751885cc
Code: Select all
git revert 935df1bd40d43c4ee91838c42a20e9af751885cc
Code: Select all
[detached HEAD 24ee1d8b315c] Revert "of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw()"
2 files changed, 51 insertions(+), 77 deletions(-)
Last edited by xeno74 on Mon Jul 01, 2024 8:42 am, edited 1 time in total.
Re: New kernels
I was able to revert the first bad commit in the latest git kernel. 

Code: Select all
$ git revert 935df1bd40d43c4ee91838c42a20e9af751885cc
[master fddf986bbc8c] Revert "of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw()"
2 files changed, 51 insertions(+), 77 deletions(-)
Re: New kernels
I created a patch.
of_irq.patch:
Unfortunately it doesn't compile with this patch.
Error message:
of_irq.patch:
Code: Select all
diff -rupN a/drivers/of/irq.c b/drivers/of/irq.c
--- a/drivers/of/irq.c 2024-06-29 15:01:01.012144747 +0200
+++ b/drivers/of/irq.c 2024-06-29 15:00:33.514501761 +0200
@@ -25,8 +25,6 @@
#include <linux/string.h>
#include <linux/slab.h>
-#include "of_private.h"
-
/**
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
* @dev: Device node of the device whose interrupt is to be mapped
@@ -98,57 +96,6 @@ static const char * const of_irq_imap_ab
NULL,
};
-const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_phandle_args *out_irq)
-{
- u32 intsize, addrsize;
- struct device_node *np;
-
- /* Get the interrupt parent */
- if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
- np = of_node_get(of_irq_dflt_pic);
- else
- np = of_find_node_by_phandle(be32_to_cpup(imap));
- imap++;
-
- /* Check if not found */
- if (!np) {
- pr_debug(" -> imap parent not found !\n");
- return NULL;
- }
-
- /* Get #interrupt-cells and #address-cells of new parent */
- if (of_property_read_u32(np, "#interrupt-cells",
- &intsize)) {
- pr_debug(" -> parent lacks #interrupt-cells!\n");
- of_node_put(np);
- return NULL;
- }
- if (of_property_read_u32(np, "#address-cells",
- &addrsize))
- addrsize = 0;
-
- pr_debug(" -> intsize=%d, addrsize=%d\n",
- intsize, addrsize);
-
- /* Check for malformed properties */
- if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)
- || (len < (addrsize + intsize))) {
- of_node_put(np);
- return NULL;
- }
-
- pr_debug(" -> imaplen=%d\n", len);
-
- imap += addrsize + intsize;
-
- out_irq->np = np;
- for (int i = 0; i < intsize; i++)
- out_irq->args[i] = be32_to_cpup(imap - intsize + i);
- out_irq->args_count = intsize;
-
- return imap;
-}
-
/**
* of_irq_parse_raw - Low level interrupt tree parsing
* @addr: address specifier (start of "reg" property of the device) in be32 format
@@ -165,12 +112,12 @@ const __be32 *of_irq_parse_imap_parent(c
*/
int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
{
- struct device_node *ipar, *tnode, *old = NULL;
+ struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
__be32 initial_match_array[MAX_PHANDLE_ARGS];
const __be32 *match_array = initial_match_array;
- const __be32 *tmp, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
- u32 intsize = 1, addrsize;
- int i, rc = -EINVAL;
+ const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
+ u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+ int imaplen, match, i, rc = -EINVAL;
#ifdef DEBUG
of_print_phandle_args("of_irq_parse_raw: ", out_irq);
@@ -229,9 +176,6 @@ int of_irq_parse_raw(const __be32 *addr,
/* Now start the actual "proper" walk of the interrupt tree */
while (ipar != NULL) {
- int imaplen, match;
- const __be32 *imap, *oldimap, *imask;
- struct device_node *newpar;
/*
* Now check if cursor is an interrupt-controller and
* if it is then we are done, unless there is an
@@ -272,7 +216,7 @@ int of_irq_parse_raw(const __be32 *addr,
/* Parse interrupt-map */
match = 0;
- while (imaplen > (addrsize + intsize + 1)) {
+ while (imaplen > (addrsize + intsize + 1) && !match) {
/* Compare specifiers */
match = 1;
for (i = 0; i < (addrsize + intsize); i++, imaplen--)
@@ -280,17 +224,48 @@ int of_irq_parse_raw(const __be32 *addr,
pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
- oldimap = imap;
- imap = of_irq_parse_imap_parent(oldimap, imaplen, out_irq);
- if (!imap)
+ /* Get the interrupt parent */
+ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
+ newpar = of_node_get(of_irq_dflt_pic);
+ else
+ newpar = of_find_node_by_phandle(be32_to_cpup(imap));
+ imap++;
+ --imaplen;
+
+ /* Check if not found */
+ if (newpar == NULL) {
+ pr_debug(" -> imap parent not found !\n");
goto fail;
+ }
- match &= of_device_is_available(out_irq->np);
- if (match)
- break;
+ if (!of_device_is_available(newpar))
+ match = 0;
+
+ /* Get #interrupt-cells and #address-cells of new
+ * parent
+ */
+ if (of_property_read_u32(newpar, "#interrupt-cells",
+ &newintsize)) {
+ pr_debug(" -> parent lacks #interrupt-cells!\n");
+ goto fail;
+ }
+ if (of_property_read_u32(newpar, "#address-cells",
+ &newaddrsize))
+ newaddrsize = 0;
+
+ pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
+ newintsize, newaddrsize);
+
+ /* Check for malformed properties */
+ if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)
+ || (imaplen < (newaddrsize + newintsize))) {
+ rc = -EFAULT;
+ goto fail;
+ }
+
+ imap += newaddrsize + newintsize;
+ imaplen -= newaddrsize + newintsize;
- of_node_put(out_irq->np);
- imaplen -= imap - oldimap;
pr_debug(" -> imaplen=%d\n", imaplen);
}
if (!match) {
@@ -312,11 +287,11 @@ int of_irq_parse_raw(const __be32 *addr,
* Successfully parsed an interrupt-map translation; copy new
* interrupt specifier into the out_irq structure
*/
- match_array = oldimap + 1;
-
- newpar = out_irq->np;
- intsize = out_irq->args_count;
- addrsize = (imap - match_array) - intsize;
+ match_array = imap - newaddrsize - newintsize;
+ for (i = 0; i < newintsize; i++)
+ out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
+ out_irq->args_count = intsize = newintsize;
+ addrsize = newaddrsize;
if (ipar == newpar) {
pr_debug("%pOF interrupt-map entry to self\n", ipar);
@@ -325,6 +300,7 @@ int of_irq_parse_raw(const __be32 *addr,
skiplevel:
/* Iterate again with new parent */
+ out_irq->np = newpar;
pr_debug(" -> new parent: %pOF\n", newpar);
of_node_put(ipar);
ipar = newpar;
@@ -334,6 +310,7 @@ int of_irq_parse_raw(const __be32 *addr,
fail:
of_node_put(ipar);
+ of_node_put(newpar);
return rc;
}
diff -rupN a/drivers/of/of_private.h b/drivers/of/of_private.h
--- a/drivers/of/of_private.h 2024-06-29 15:01:01.012144747 +0200
+++ b/drivers/of/of_private.h 2024-06-29 15:00:33.514501761 +0200
@@ -159,9 +159,6 @@ extern void __of_sysfs_remove_bin_file(s
extern int of_bus_n_addr_cells(struct device_node *np);
extern int of_bus_n_size_cells(struct device_node *np);
-const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len,
- struct of_phandle_args *out_irq);
-
struct bus_dma_region;
#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
int of_dma_get_range(struct device_node *np,
Error message:
Code: Select all
drivers/of/property.c: In function 'parse_interrupt_map':
drivers/of/property.c:1334:10: error: implicit declaration of function 'of_irq_parse_imap_parent' [-Werror=implicit-function-declaration]
1334 | imap = of_irq_parse_imap_parent(imap, imap_end - imap, &sup_args);
Re: New kernels
I created a new patch.
of_irq_v2.patch:
of_irq_v2.patch:
Code: Select all
diff -rupN a/drivers/of/irq.c b/drivers/of/irq.c
--- a/drivers/of/irq.c 2024-06-23 23:08:54.000000000 +0200
+++ b/drivers/of/irq.c 2024-06-29 16:01:29.161973980 +0200
@@ -25,8 +25,6 @@
#include <linux/string.h>
#include <linux/slab.h>
-#include "of_private.h"
-
/**
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
* @dev: Device node of the device whose interrupt is to be mapped
@@ -98,57 +96,6 @@ static const char * const of_irq_imap_ab
NULL,
};
-const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_phandle_args *out_irq)
-{
- u32 intsize, addrsize;
- struct device_node *np;
-
- /* Get the interrupt parent */
- if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
- np = of_node_get(of_irq_dflt_pic);
- else
- np = of_find_node_by_phandle(be32_to_cpup(imap));
- imap++;
-
- /* Check if not found */
- if (!np) {
- pr_debug(" -> imap parent not found !\n");
- return NULL;
- }
-
- /* Get #interrupt-cells and #address-cells of new parent */
- if (of_property_read_u32(np, "#interrupt-cells",
- &intsize)) {
- pr_debug(" -> parent lacks #interrupt-cells!\n");
- of_node_put(np);
- return NULL;
- }
- if (of_property_read_u32(np, "#address-cells",
- &addrsize))
- addrsize = 0;
-
- pr_debug(" -> intsize=%d, addrsize=%d\n",
- intsize, addrsize);
-
- /* Check for malformed properties */
- if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)
- || (len < (addrsize + intsize))) {
- of_node_put(np);
- return NULL;
- }
-
- pr_debug(" -> imaplen=%d\n", len);
-
- imap += addrsize + intsize;
-
- out_irq->np = np;
- for (int i = 0; i < intsize; i++)
- out_irq->args[i] = be32_to_cpup(imap - intsize + i);
- out_irq->args_count = intsize;
-
- return imap;
-}
-
/**
* of_irq_parse_raw - Low level interrupt tree parsing
* @addr: address specifier (start of "reg" property of the device) in be32 format
@@ -165,12 +112,12 @@ const __be32 *of_irq_parse_imap_parent(c
*/
int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
{
- struct device_node *ipar, *tnode, *old = NULL;
+ struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
__be32 initial_match_array[MAX_PHANDLE_ARGS];
const __be32 *match_array = initial_match_array;
- const __be32 *tmp, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
- u32 intsize = 1, addrsize;
- int i, rc = -EINVAL;
+ const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
+ u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+ int imaplen, match, i, rc = -EINVAL;
#ifdef DEBUG
of_print_phandle_args("of_irq_parse_raw: ", out_irq);
@@ -229,9 +176,6 @@ int of_irq_parse_raw(const __be32 *addr,
/* Now start the actual "proper" walk of the interrupt tree */
while (ipar != NULL) {
- int imaplen, match;
- const __be32 *imap, *oldimap, *imask;
- struct device_node *newpar;
/*
* Now check if cursor is an interrupt-controller and
* if it is then we are done, unless there is an
@@ -272,7 +216,7 @@ int of_irq_parse_raw(const __be32 *addr,
/* Parse interrupt-map */
match = 0;
- while (imaplen > (addrsize + intsize + 1)) {
+ while (imaplen > (addrsize + intsize + 1) && !match) {
/* Compare specifiers */
match = 1;
for (i = 0; i < (addrsize + intsize); i++, imaplen--)
@@ -280,17 +224,48 @@ int of_irq_parse_raw(const __be32 *addr,
pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
- oldimap = imap;
- imap = of_irq_parse_imap_parent(oldimap, imaplen, out_irq);
- if (!imap)
+ /* Get the interrupt parent */
+ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
+ newpar = of_node_get(of_irq_dflt_pic);
+ else
+ newpar = of_find_node_by_phandle(be32_to_cpup(imap));
+ imap++;
+ --imaplen;
+
+ /* Check if not found */
+ if (newpar == NULL) {
+ pr_debug(" -> imap parent not found !\n");
goto fail;
+ }
- match &= of_device_is_available(out_irq->np);
- if (match)
- break;
+ if (!of_device_is_available(newpar))
+ match = 0;
+
+ /* Get #interrupt-cells and #address-cells of new
+ * parent
+ */
+ if (of_property_read_u32(newpar, "#interrupt-cells",
+ &newintsize)) {
+ pr_debug(" -> parent lacks #interrupt-cells!\n");
+ goto fail;
+ }
+ if (of_property_read_u32(newpar, "#address-cells",
+ &newaddrsize))
+ newaddrsize = 0;
+
+ pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
+ newintsize, newaddrsize);
+
+ /* Check for malformed properties */
+ if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)
+ || (imaplen < (newaddrsize + newintsize))) {
+ rc = -EFAULT;
+ goto fail;
+ }
+
+ imap += newaddrsize + newintsize;
+ imaplen -= newaddrsize + newintsize;
- of_node_put(out_irq->np);
- imaplen -= imap - oldimap;
pr_debug(" -> imaplen=%d\n", imaplen);
}
if (!match) {
@@ -312,11 +287,11 @@ int of_irq_parse_raw(const __be32 *addr,
* Successfully parsed an interrupt-map translation; copy new
* interrupt specifier into the out_irq structure
*/
- match_array = oldimap + 1;
-
- newpar = out_irq->np;
- intsize = out_irq->args_count;
- addrsize = (imap - match_array) - intsize;
+ match_array = imap - newaddrsize - newintsize;
+ for (i = 0; i < newintsize; i++)
+ out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
+ out_irq->args_count = intsize = newintsize;
+ addrsize = newaddrsize;
if (ipar == newpar) {
pr_debug("%pOF interrupt-map entry to self\n", ipar);
@@ -325,6 +300,7 @@ int of_irq_parse_raw(const __be32 *addr,
skiplevel:
/* Iterate again with new parent */
+ out_irq->np = newpar;
pr_debug(" -> new parent: %pOF\n", newpar);
of_node_put(ipar);
ipar = newpar;
@@ -334,6 +310,7 @@ int of_irq_parse_raw(const __be32 *addr,
fail:
of_node_put(ipar);
+ of_node_put(newpar);
return rc;
}
diff -rupN a/drivers/of/of_private.h b/drivers/of/of_private.h
--- a/drivers/of/of_private.h 2024-06-23 23:08:54.000000000 +0200
+++ b/drivers/of/of_private.h 2024-06-29 16:01:29.166973915 +0200
@@ -159,9 +159,6 @@ extern void __of_sysfs_remove_bin_file(s
extern int of_bus_n_addr_cells(struct device_node *np);
extern int of_bus_n_size_cells(struct device_node *np);
-const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len,
- struct of_phandle_args *out_irq);
-
struct bus_dma_region;
#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
int of_dma_get_range(struct device_node *np,
diff -rupN a/drivers/of/property.c b/drivers/of/property.c
--- a/drivers/of/property.c 2024-06-23 23:08:54.000000000 +0200
+++ b/drivers/of/property.c 2024-06-29 16:02:54.141867362 +0200
@@ -1306,10 +1306,10 @@ static struct device_node *parse_interru
static struct device_node *parse_interrupt_map(struct device_node *np,
const char *prop_name, int index)
{
- const __be32 *imap, *imap_end;
+ const __be32 *imap, *imap_end, *addr;
struct of_phandle_args sup_args;
u32 addrcells, intcells;
- int imaplen;
+ int i, imaplen;
if (!IS_ENABLED(CONFIG_OF_IRQ))
return NULL;
@@ -1322,23 +1322,33 @@ static struct device_node *parse_interru
addrcells = of_bus_n_addr_cells(np);
imap = of_get_property(np, "interrupt-map", &imaplen);
- imaplen /= sizeof(*imap);
- if (!imap)
+ if (!imap || imaplen <= (addrcells + intcells))
return NULL;
-
imap_end = imap + imaplen;
- for (int i = 0; imap + addrcells + intcells + 1 < imap_end; i++) {
- imap += addrcells + intcells;
-
- imap = of_irq_parse_imap_parent(imap, imap_end - imap, &sup_args);
- if (!imap)
+ while (imap < imap_end) {
+ addr = imap;
+ imap += addrcells;
+
+ sup_args.np = np;
+ sup_args.args_count = intcells;
+ for (i = 0; i < intcells; i++)
+ sup_args.args[i] = be32_to_cpu(imap[i]);
+ imap += intcells;
+
+ /*
+ * Upon success, the function of_irq_parse_raw() returns
+ * interrupt controller DT node pointer in sup_args.np.
+ */
+ if (of_irq_parse_raw(addr, &sup_args))
return NULL;
- if (i == index)
+ if (!index)
return sup_args.np;
of_node_put(sup_args.np);
+ imap += sup_args.args_count + 1;
+ index--;
}
return NULL;