diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-19 08:38:51 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-19 08:38:51 +0200 |
commit | 2a17bb8c204f2b6461524a1b52ace2dbe097eaf7 (patch) | |
tree | 045f96e6812af682cb42f280a3a9ccb89132addb /drivers | |
parent | 19a519ca87b59a0031e1295674b1af0d6da83f70 (diff) | |
parent | 0c36680c0e2d959cc264a1e65628c825f7f87add (diff) |
Merge tag 'devicetree-for-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree updates from Rob Herring:
"DT Bindings:
- Drop duplicate devices in trivial-devices.yaml
- Add a common serial peripheral device schema and reference it in
serial device schemas.
- Convert nxp,lpc1850-wdt, zii,rave-wdt, ti,davinci-wdt,
snps,archs-pct, fsl,bcsr, fsl,fpga-qixis-i2c, fsl,fpga-qixis,
fsl,cpm-enet, fsl,cpm-mdio, fsl,ucc-hdlc, maxim,ds26522,
aspeed,ast2400-cvic, aspeed,ast2400-vic, fsl,ftm-timer,
ti,davinci-timer, fsl,rcpm, and qcom,ebi2 to DT schema
- Add support for rockchip,rk3576-wdt, qcom,apss-wdt-sa8255p,
fsl,imx8qm-irqsteer, qcom,pm6150-vib, qcom,sa8255p-pdc,
isil,isl69260, ti,tps546d24, and lpc32xx DMA mux
- Drop duplicate nvidia,tegra186-ccplex-cluster.yaml and
mediatek,mt6795-sys-clock.yaml
- Add arm,gic ESPI and EPPI interrupt type specifiers
- Add another batch of legacy compatible strings which we have no
intention of documenting
- Add dmas/dma-names properties to FSL lcdif
- Fix wakeup-source reference to m8921-keypad.yaml
- Treewide fixes of typos in bindings
DT Core:
- Update dtc/libfdt to upstream version v1.7.0-95-gbcd02b523429
- More conversions to scoped iterators and __free() initializer
- Handle overflows in address resources on 32-bit systems
- Extend extracting compatible strings in sources from function
parameters
- Use of_property_present() in DT unittest
- Clean-up of_irq_to_resource() to use helpers
- Support #msi-cells=<0> in of_msi_get_domain()
- Improve the kerneldoc for of_property_match_string()
- kselftest: Ignore nodes that have ancestors disabled"
* tag 'devicetree-for-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (59 commits)
dt-bindings: watchdog: Add rockchip,rk3576-wdt compatible
dt-bindings: cpu: Drop duplicate nvidia,tegra186-ccplex-cluster.yaml
dt-bindings: clock: mediatek: Drop duplicate mediatek,mt6795-sys-clock.yaml
of/irq: Use helper to define resources
of/irq: Make use of irq_get_trigger_type()
dt-bindings: clk: vc5: Make SD/OE pin configuration properties not required
drivers/of: Improve documentation for match_string
of: property: Do some clean up with use of __free()
dt-bindings: watchdog: qcom-wdt: document support on SA8255p
dt-bindings: interrupt-controller: fsl,irqsteer: Document fsl,imx8qm-irqsteer
dt-bindings: interrupt-controller: arm,gic: add ESPI and EPPI specifiers
dt-bindings: dma: Add lpc32xx DMA mux binding
dt-bindings: trivial-devices: Drop duplicate "maxim,max1237"
dt-bindings: trivial-devices: Drop duplicate LM75 compatible devices
dt-bindings: trivial-devices: Deprecate "ad,ad7414"
dt-bindings: trivial-devices: Drop incorrect and duplicate at24 compatibles
dt-bindings: wakeup-source: update reference to m8921-keypad.yaml
dt-bindings: interrupt-controller: qcom-pdc: document support for SA8255p
dt-bindings: Fix various typos
of: address: Unify resource bounds overflow checking
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/of/address.c | 40 | ||||
-rw-r--r-- | drivers/of/irq.c | 43 | ||||
-rw-r--r-- | drivers/of/overlay.c | 12 | ||||
-rw-r--r-- | drivers/of/platform.c | 14 | ||||
-rw-r--r-- | drivers/of/property.c | 41 | ||||
-rw-r--r-- | drivers/of/resolver.c | 12 | ||||
-rw-r--r-- | drivers/of/unittest.c | 4 |
7 files changed, 66 insertions, 100 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index d669ce25b5f9..286f0c161e33 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -8,6 +8,7 @@ #include <linux/logic_pio.h> #include <linux/module.h> #include <linux/of_address.h> +#include <linux/overflow.h> #include <linux/pci.h> #include <linux/pci_regs.h> #include <linux/sizes.h> @@ -197,6 +198,23 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, #endif /* CONFIG_PCI */ +static int __of_address_resource_bounds(struct resource *r, u64 start, u64 size) +{ + u64 end = start; + + if (overflows_type(start, r->start)) + return -EOVERFLOW; + if (size && check_add_overflow(end, size - 1, &end)) + return -EOVERFLOW; + if (overflows_type(end, r->end)) + return -EOVERFLOW; + + r->start = start; + r->end = end; + + return 0; +} + /* * of_pci_range_to_resource - Create a resource from an of_pci_range * @range: the PCI range that describes the resource @@ -215,6 +233,7 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, int of_pci_range_to_resource(struct of_pci_range *range, struct device_node *np, struct resource *res) { + u64 start; int err; res->flags = range->flags; res->parent = res->child = res->sibling = NULL; @@ -231,18 +250,11 @@ int of_pci_range_to_resource(struct of_pci_range *range, err = -EINVAL; goto invalid_range; } - res->start = port; + start = port; } else { - if ((sizeof(resource_size_t) < 8) && - upper_32_bits(range->cpu_addr)) { - err = -EINVAL; - goto invalid_range; - } - - res->start = range->cpu_addr; + start = range->cpu_addr; } - res->end = res->start + range->size - 1; - return 0; + return __of_address_resource_bounds(res, start, range->size); invalid_range: res->start = (resource_size_t)OF_BAD_ADDR; @@ -258,8 +270,8 @@ EXPORT_SYMBOL(of_pci_range_to_resource); * @res: pointer to a valid resource that will be updated to * reflect the values contained in the range. * - * Returns ENOENT if the entry is not found or EINVAL if the range cannot be - * converted to resource. + * Returns -ENOENT if the entry is not found or -EOVERFLOW if the range + * cannot be converted to resource. */ int of_range_to_resource(struct device_node *np, int index, struct resource *res) { @@ -1061,12 +1073,10 @@ static int __of_address_to_resource(struct device_node *dev, int index, int bar_ if (of_mmio_is_nonposted(dev)) flags |= IORESOURCE_MEM_NONPOSTED; - r->start = taddr; - r->end = taddr + size - 1; r->flags = flags; r->name = name ? name : dev->full_name; - return 0; + return __of_address_resource_bounds(r, taddr, size); } /** diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 8fd63100ba8f..a494f56a0d0e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -357,8 +357,8 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar addr = of_get_property(device, "reg", &addr_len); /* Prevent out-of-bounds read in case of longer interrupt parent address size */ - if (addr_len > (3 * sizeof(__be32))) - addr_len = 3 * sizeof(__be32); + if (addr_len > sizeof(addr_buf)) + addr_len = sizeof(addr_buf); if (addr) memcpy(addr_buf, addr, addr_len); @@ -429,9 +429,8 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) of_property_read_string_index(dev, "interrupt-names", index, &name); - r->start = r->end = irq; - r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq)); - r->name = name ? name : of_node_full_name(dev); + *r = DEFINE_RES_IRQ_NAMED(irq, name ?: of_node_full_name(dev)); + r->flags |= irq_get_trigger_type(irq); } return irq; @@ -716,8 +715,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id, * @np: device node for @dev * @token: bus type for this domain * - * Parse the msi-parent property (both the simple and the complex - * versions), and returns the corresponding MSI domain. + * Parse the msi-parent property and returns the corresponding MSI domain. * * Returns: the MSI domain for this device (or NULL on failure). */ @@ -725,33 +723,14 @@ struct irq_domain *of_msi_get_domain(struct device *dev, struct device_node *np, enum irq_domain_bus_token token) { - struct device_node *msi_np; + struct of_phandle_iterator it; struct irq_domain *d; + int err; - /* Check for a single msi-parent property */ - msi_np = of_parse_phandle(np, "msi-parent", 0); - if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) { - d = irq_find_matching_host(msi_np, token); - if (!d) - of_node_put(msi_np); - return d; - } - - if (token == DOMAIN_BUS_PLATFORM_MSI) { - /* Check for the complex msi-parent version */ - struct of_phandle_args args; - int index = 0; - - while (!of_parse_phandle_with_args(np, "msi-parent", - "#msi-cells", - index, &args)) { - d = irq_find_matching_host(args.np, token); - if (d) - return d; - - of_node_put(args.np); - index++; - } + of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) { + d = irq_find_matching_host(it.node, token); + if (d) + return d; } return NULL; diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 4d861a75d694..cbdecccca097 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -472,7 +472,6 @@ static int add_changeset_node(struct overlay_changeset *ovcs, static int build_changeset_next_level(struct overlay_changeset *ovcs, struct target *target, const struct device_node *overlay_node) { - struct device_node *child; struct property *prop; int ret; @@ -485,12 +484,11 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, } } - for_each_child_of_node(overlay_node, child) { + for_each_child_of_node_scoped(overlay_node, child) { ret = add_changeset_node(ovcs, target, child); if (ret) { pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n", target->np, child, ret); - of_node_put(child); return ret; } } @@ -1078,16 +1076,12 @@ EXPORT_SYMBOL_GPL(of_overlay_fdt_apply); */ static int find_node(struct device_node *tree, struct device_node *np) { - struct device_node *child; - if (tree == np) return 1; - for_each_child_of_node(tree, child) { - if (find_node(child, np)) { - of_node_put(child); + for_each_child_of_node_scoped(tree, child) { + if (find_node(child, np)) return 1; - } } return 0; diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ef622d41eb5b..f416c008cec2 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -338,7 +338,6 @@ static int of_platform_bus_create(struct device_node *bus, struct device *parent, bool strict) { const struct of_dev_auxdata *auxdata; - struct device_node *child; struct platform_device *dev; const char *bus_id = NULL; void *platform_data = NULL; @@ -382,13 +381,11 @@ static int of_platform_bus_create(struct device_node *bus, if (!dev || !of_match_node(matches, bus)) return 0; - for_each_child_of_node(bus, child) { + for_each_child_of_node_scoped(bus, child) { pr_debug(" create child: %pOF\n", child); rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict); - if (rc) { - of_node_put(child); + if (rc) break; - } } of_node_set_flag(bus, OF_POPULATED_BUS); return rc; @@ -459,7 +456,6 @@ int of_platform_populate(struct device_node *root, const struct of_dev_auxdata *lookup, struct device *parent) { - struct device_node *child; int rc = 0; root = root ? of_node_get(root) : of_find_node_by_path("/"); @@ -470,12 +466,10 @@ int of_platform_populate(struct device_node *root, pr_debug(" starting at: %pOF\n", root); device_links_supplier_sync_state_pause(); - for_each_child_of_node(root, child) { + for_each_child_of_node_scoped(root, child) { rc = of_platform_bus_create(child, matches, lookup, parent, true); - if (rc) { - of_node_put(child); + if (rc) break; - } } device_links_supplier_sync_state_resume(); diff --git a/drivers/of/property.c b/drivers/of/property.c index 164d77cb9445..11b922fde7af 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -452,12 +452,17 @@ EXPORT_SYMBOL_GPL(of_property_read_string); /** * of_property_match_string() - Find string in a list and return index - * @np: pointer to node containing string list property + * @np: pointer to the node containing the string list property * @propname: string list property name - * @string: pointer to string to search for in string list + * @string: pointer to the string to search for in the string list * - * This function searches a string list property and returns the index - * of a specific string value. + * Search for an exact match of string in a device node property which is a + * string of lists. + * + * Return: the index of the first occurrence of the string on success, -EINVAL + * if the property does not exist, -ENODATA if the property does not have a + * value, and -EILSEQ if the string is not null-terminated within the length of + * the property data. */ int of_property_match_string(const struct device_node *np, const char *propname, const char *string) @@ -773,16 +778,11 @@ EXPORT_SYMBOL(of_graph_get_port_parent); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { - struct device_node *np, *pp; - /* Get remote endpoint node. */ - np = of_graph_get_remote_endpoint(node); - - pp = of_graph_get_port_parent(np); + struct device_node *np __free(device_node) = + of_graph_get_remote_endpoint(node); - of_node_put(np); - - return pp; + return of_graph_get_port_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port_parent); @@ -1064,19 +1064,15 @@ static void of_link_to_phandle(struct device_node *con_np, struct device_node *sup_np, u8 flags) { - struct device_node *tmp_np = of_node_get(sup_np); + struct device_node *tmp_np __free(device_node) = of_node_get(sup_np); /* Check that sup_np and its ancestors are available. */ while (tmp_np) { - if (of_fwnode_handle(tmp_np)->dev) { - of_node_put(tmp_np); + if (of_fwnode_handle(tmp_np)->dev) break; - } - if (!of_device_is_available(tmp_np)) { - of_node_put(tmp_np); + if (!of_device_is_available(tmp_np)) return; - } tmp_np = of_get_next_parent(tmp_np); } @@ -1440,16 +1436,13 @@ static int of_link_property(struct device_node *con_np, const char *prop_name) } while ((phandle = s->parse_prop(con_np, prop_name, i))) { - struct device_node *con_dev_np; + struct device_node *con_dev_np __free(device_node) = + s->get_con_dev ? s->get_con_dev(con_np) : of_node_get(con_np); - con_dev_np = s->get_con_dev - ? s->get_con_dev(con_np) - : of_node_get(con_np); matched = true; i++; of_link_to_phandle(con_dev_np, phandle, s->fwlink_flags); of_node_put(phandle); - of_node_put(con_dev_np); } s++; } diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 2780928764a4..5cf96776dd7d 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -150,7 +150,7 @@ static int node_name_cmp(const struct device_node *dn1, static int adjust_local_phandle_references(struct device_node *local_fixups, struct device_node *overlay, int phandle_delta) { - struct device_node *child, *overlay_child; + struct device_node *overlay_child; struct property *prop_fix, *prop; int err, i, count; unsigned int off; @@ -194,7 +194,7 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, * The roots of the subtrees are the overlay's __local_fixups__ node * and the overlay's root node. */ - for_each_child_of_node(local_fixups, child) { + for_each_child_of_node_scoped(local_fixups, child) { for_each_child_of_node(overlay, overlay_child) if (!node_name_cmp(child, overlay_child)) { @@ -202,17 +202,13 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, break; } - if (!overlay_child) { - of_node_put(child); + if (!overlay_child) return -EINVAL; - } err = adjust_local_phandle_references(child, overlay_child, phandle_delta); - if (err) { - of_node_put(child); + if (err) return err; - } } return 0; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index c830f346df45..b60b4b7d7172 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -900,8 +900,8 @@ static void __init of_unittest_changeset(void) unittest(!of_find_node_by_path("/testcase-data/changeset/n2/n21"), "'%pOF' still present after revert\n", n21); - ppremove = of_find_property(parent, "prop-remove", NULL); - unittest(ppremove, "failed to find removed prop after revert\n"); + unittest(of_property_present(parent, "prop-remove"), + "failed to find removed prop after revert\n"); ret = of_property_read_string(parent, "prop-update", &propstr); unittest(!ret, "failed to find updated prop after revert\n"); |