Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 5121452

Browse files
committed
Merge tag 'devicetree-fixes-for-6.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree fixes from Rob Herring: - Fix regression in 'interrupt-map' handling affecting Apple M1 mini (at least) - Fix binding example warning in stm32 st,mlahb binding - Fix schema error in Allwinner platform binding causing lots of spurious warnings - Add missing MODULE_DESCRIPTION() to DT kunit tests * tag 'devicetree-fixes-for-6.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: of: property: Fix fw_devlink handling of interrupt-map of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() dt-bindings: arm: stm32: st,mlahb: Drop spurious "reg" property from example dt-bindings: arm: sunxi: Fix incorrect '-' usage of: of_test: add MODULE_DESCRIPTION()
2 parents 32f88d6 + e7985f4 commit 5121452

File tree

6 files changed

+92
-76
lines changed

6 files changed

+92
-76
lines changed

Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,10 @@ unevaluatedProperties: false
5454

5555
examples:
5656
- |
57-
mlahb: ahb@38000000 {
57+
ahb {
5858
compatible = "st,mlahb", "simple-bus";
5959
#address-cells = <1>;
6060
#size-cells = <1>;
61-
reg = <0x10000000 0x40000>;
6261
ranges;
6362
dma-ranges = <0x00000000 0x38000000 0x10000>,
6463
<0x10000000 0x10000000 0x60000>,

Documentation/devicetree/bindings/arm/sunxi.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,17 @@ properties:
5757
- const: allwinner,sun8i-v3s
5858

5959
- description: Anbernic RG35XX (2024)
60-
- items:
60+
items:
6161
- const: anbernic,rg35xx-2024
6262
- const: allwinner,sun50i-h700
6363

6464
- description: Anbernic RG35XX Plus
65-
- items:
65+
items:
6666
- const: anbernic,rg35xx-plus
6767
- const: allwinner,sun50i-h700
6868

6969
- description: Anbernic RG35XX H
70-
- items:
70+
items:
7171
- const: anbernic,rg35xx-h
7272
- const: allwinner,sun50i-h700
7373

drivers/of/irq.c

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <linux/string.h>
2626
#include <linux/slab.h>
2727

28+
#include "of_private.h"
29+
2830
/**
2931
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
3032
* @dev: Device node of the device whose interrupt is to be mapped
@@ -96,6 +98,57 @@ static const char * const of_irq_imap_abusers[] = {
9698
NULL,
9799
};
98100

101+
const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_phandle_args *out_irq)
102+
{
103+
u32 intsize, addrsize;
104+
struct device_node *np;
105+
106+
/* Get the interrupt parent */
107+
if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
108+
np = of_node_get(of_irq_dflt_pic);
109+
else
110+
np = of_find_node_by_phandle(be32_to_cpup(imap));
111+
imap++;
112+
113+
/* Check if not found */
114+
if (!np) {
115+
pr_debug(" -> imap parent not found !\n");
116+
return NULL;
117+
}
118+
119+
/* Get #interrupt-cells and #address-cells of new parent */
120+
if (of_property_read_u32(np, "#interrupt-cells",
121+
&intsize)) {
122+
pr_debug(" -> parent lacks #interrupt-cells!\n");
123+
of_node_put(np);
124+
return NULL;
125+
}
126+
if (of_property_read_u32(np, "#address-cells",
127+
&addrsize))
128+
addrsize = 0;
129+
130+
pr_debug(" -> intsize=%d, addrsize=%d\n",
131+
intsize, addrsize);
132+
133+
/* Check for malformed properties */
134+
if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)
135+
|| (len < (addrsize + intsize))) {
136+
of_node_put(np);
137+
return NULL;
138+
}
139+
140+
pr_debug(" -> imaplen=%d\n", len);
141+
142+
imap += addrsize + intsize;
143+
144+
out_irq->np = np;
145+
for (int i = 0; i < intsize; i++)
146+
out_irq->args[i] = be32_to_cpup(imap - intsize + i);
147+
out_irq->args_count = intsize;
148+
149+
return imap;
150+
}
151+
99152
/**
100153
* of_irq_parse_raw - Low level interrupt tree parsing
101154
* @addr: address specifier (start of "reg" property of the device) in be32 format
@@ -112,12 +165,12 @@ static const char * const of_irq_imap_abusers[] = {
112165
*/
113166
int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
114167
{
115-
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
168+
struct device_node *ipar, *tnode, *old = NULL;
116169
__be32 initial_match_array[MAX_PHANDLE_ARGS];
117170
const __be32 *match_array = initial_match_array;
118-
const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
119-
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
120-
int imaplen, match, i, rc = -EINVAL;
171+
const __be32 *tmp, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
172+
u32 intsize = 1, addrsize;
173+
int i, rc = -EINVAL;
121174

122175
#ifdef DEBUG
123176
of_print_phandle_args("of_irq_parse_raw: ", out_irq);
@@ -176,6 +229,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
176229

177230
/* Now start the actual "proper" walk of the interrupt tree */
178231
while (ipar != NULL) {
232+
int imaplen, match;
233+
const __be32 *imap, *oldimap, *imask;
234+
struct device_node *newpar;
179235
/*
180236
* Now check if cursor is an interrupt-controller and
181237
* if it is then we are done, unless there is an
@@ -216,56 +272,25 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
216272

217273
/* Parse interrupt-map */
218274
match = 0;
219-
while (imaplen > (addrsize + intsize + 1) && !match) {
275+
while (imaplen > (addrsize + intsize + 1)) {
220276
/* Compare specifiers */
221277
match = 1;
222278
for (i = 0; i < (addrsize + intsize); i++, imaplen--)
223279
match &= !((match_array[i] ^ *imap++) & imask[i]);
224280

225281
pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
226282

227-
/* Get the interrupt parent */
228-
if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
229-
newpar = of_node_get(of_irq_dflt_pic);
230-
else
231-
newpar = of_find_node_by_phandle(be32_to_cpup(imap));
232-
imap++;
233-
--imaplen;
234-
235-
/* Check if not found */
236-
if (newpar == NULL) {
237-
pr_debug(" -> imap parent not found !\n");
238-
goto fail;
239-
}
240-
241-
if (!of_device_is_available(newpar))
242-
match = 0;
243-
244-
/* Get #interrupt-cells and #address-cells of new
245-
* parent
246-
*/
247-
if (of_property_read_u32(newpar, "#interrupt-cells",
248-
&newintsize)) {
249-
pr_debug(" -> parent lacks #interrupt-cells!\n");
250-
goto fail;
251-
}
252-
if (of_property_read_u32(newpar, "#address-cells",
253-
&newaddrsize))
254-
newaddrsize = 0;
255-
256-
pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
257-
newintsize, newaddrsize);
258-
259-
/* Check for malformed properties */
260-
if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)
261-
|| (imaplen < (newaddrsize + newintsize))) {
262-
rc = -EFAULT;
283+
oldimap = imap;
284+
imap = of_irq_parse_imap_parent(oldimap, imaplen, out_irq);
285+
if (!imap)
263286
goto fail;
264-
}
265287

266-
imap += newaddrsize + newintsize;
267-
imaplen -= newaddrsize + newintsize;
288+
match &= of_device_is_available(out_irq->np);
289+
if (match)
290+
break;
268291

292+
of_node_put(out_irq->np);
293+
imaplen -= imap - oldimap;
269294
pr_debug(" -> imaplen=%d\n", imaplen);
270295
}
271296
if (!match) {
@@ -287,11 +312,11 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
287312
* Successfully parsed an interrupt-map translation; copy new
288313
* interrupt specifier into the out_irq structure
289314
*/
290-
match_array = imap - newaddrsize - newintsize;
291-
for (i = 0; i < newintsize; i++)
292-
out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
293-
out_irq->args_count = intsize = newintsize;
294-
addrsize = newaddrsize;
315+
match_array = oldimap + 1;
316+
317+
newpar = out_irq->np;
318+
intsize = out_irq->args_count;
319+
addrsize = (imap - match_array) - intsize;
295320

296321
if (ipar == newpar) {
297322
pr_debug("%pOF interrupt-map entry to self\n", ipar);
@@ -300,7 +325,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
300325

301326
skiplevel:
302327
/* Iterate again with new parent */
303-
out_irq->np = newpar;
304328
pr_debug(" -> new parent: %pOF\n", newpar);
305329
of_node_put(ipar);
306330
ipar = newpar;
@@ -310,7 +334,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
310334

311335
fail:
312336
of_node_put(ipar);
313-
of_node_put(newpar);
314337

315338
return rc;
316339
}

drivers/of/of_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ extern void __of_sysfs_remove_bin_file(struct device_node *np,
159159
extern int of_bus_n_addr_cells(struct device_node *np);
160160
extern int of_bus_n_size_cells(struct device_node *np);
161161

162+
const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len,
163+
struct of_phandle_args *out_irq);
164+
162165
struct bus_dma_region;
163166
#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
164167
int of_dma_get_range(struct device_node *np,

drivers/of/of_test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ static struct kunit_suite of_dtb_suite = {
5454
kunit_test_suites(
5555
&of_dtb_suite,
5656
);
57+
MODULE_DESCRIPTION("KUnit tests for OF APIs");
5758
MODULE_LICENSE("GPL");

drivers/of/property.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,10 +1306,10 @@ static struct device_node *parse_interrupts(struct device_node *np,
13061306
static struct device_node *parse_interrupt_map(struct device_node *np,
13071307
const char *prop_name, int index)
13081308
{
1309-
const __be32 *imap, *imap_end, *addr;
1309+
const __be32 *imap, *imap_end;
13101310
struct of_phandle_args sup_args;
13111311
u32 addrcells, intcells;
1312-
int i, imaplen;
1312+
int imaplen;
13131313

13141314
if (!IS_ENABLED(CONFIG_OF_IRQ))
13151315
return NULL;
@@ -1322,33 +1322,23 @@ static struct device_node *parse_interrupt_map(struct device_node *np,
13221322
addrcells = of_bus_n_addr_cells(np);
13231323

13241324
imap = of_get_property(np, "interrupt-map", &imaplen);
1325-
if (!imap || imaplen <= (addrcells + intcells))
1325+
imaplen /= sizeof(*imap);
1326+
if (!imap)
13261327
return NULL;
1327-
imap_end = imap + imaplen;
13281328

1329-
while (imap < imap_end) {
1330-
addr = imap;
1331-
imap += addrcells;
1329+
imap_end = imap + imaplen;
13321330

1333-
sup_args.np = np;
1334-
sup_args.args_count = intcells;
1335-
for (i = 0; i < intcells; i++)
1336-
sup_args.args[i] = be32_to_cpu(imap[i]);
1337-
imap += intcells;
1331+
for (int i = 0; imap + addrcells + intcells + 1 < imap_end; i++) {
1332+
imap += addrcells + intcells;
13381333

1339-
/*
1340-
* Upon success, the function of_irq_parse_raw() returns
1341-
* interrupt controller DT node pointer in sup_args.np.
1342-
*/
1343-
if (of_irq_parse_raw(addr, &sup_args))
1334+
imap = of_irq_parse_imap_parent(imap, imap_end - imap, &sup_args);
1335+
if (!imap)
13441336
return NULL;
13451337

1346-
if (!index)
1338+
if (i == index)
13471339
return sup_args.np;
13481340

13491341
of_node_put(sup_args.np);
1350-
imap += sup_args.args_count + 1;
1351-
index--;
13521342
}
13531343

13541344
return NULL;

0 commit comments

Comments
 (0)