From dc50eab76b709d68175a358d6e23a5a3890764d3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 18 May 2024 19:39:57 +0200 Subject: Merging upstream version 6.7.7. Signed-off-by: Daniel Baumann --- drivers/of/address.c | 81 ++++------------- drivers/of/platform.c | 2 +- drivers/of/property.c | 67 ++++++-------- .../of/unittest-data/overlay_bad_unresolved.dtso | 2 +- drivers/of/unittest-data/tests-address.dtsi | 101 +++++++++++++++++++++ drivers/of/unittest.c | 89 +++++++++++++++++- 6 files changed, 234 insertions(+), 108 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 3219c51777..b59956310f 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -43,9 +43,9 @@ struct of_bus { void (*count_cells)(struct device_node *child, int *addrc, int *sizec); u64 (*map)(__be32 *addr, const __be32 *range, - int na, int ns, int pna); + int na, int ns, int pna, int fna); int (*translate)(__be32 *addr, u64 offset, int na); - bool has_flags; + int flag_cells; unsigned int (*get_flags)(const __be32 *addr); }; @@ -63,13 +63,13 @@ static void of_bus_default_count_cells(struct device_node *dev, } static u64 of_bus_default_map(__be32 *addr, const __be32 *range, - int na, int ns, int pna) + int na, int ns, int pna, int fna) { u64 cp, s, da; - cp = of_read_number(range, na); + cp = of_read_number(range + fna, na - fna); s = of_read_number(range + na + pna, ns); - da = of_read_number(addr, na); + da = of_read_number(addr + fna, na - fna); pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); @@ -101,24 +101,13 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) } static u64 of_bus_default_flags_map(__be32 *addr, const __be32 *range, int na, - int ns, int pna) + int ns, int pna, int fna) { - u64 cp, s, da; - /* Check that flags match */ if (*addr != *range) return OF_BAD_ADDR; - /* Read address values, skipping high cell */ - cp = of_read_number(range + 1, na - 1); - s = of_read_number(range + na + pna, ns); - da = of_read_number(addr + 1, na - 1); - - pr_debug("default flags map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); - - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; + return of_bus_default_map(addr, range, na, ns, pna, fna); } static int of_bus_default_flags_translate(__be32 *addr, u64 offset, int na) @@ -192,9 +181,8 @@ static void of_bus_pci_count_cells(struct device_node *np, } static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, - int pna) + int pna, int fna) { - u64 cp, s, da; unsigned int af, rf; af = of_bus_pci_get_flags(addr); @@ -204,22 +192,9 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO)) return OF_BAD_ADDR; - /* Read address values, skipping high cell */ - cp = of_read_number(range + 1, na - 1); - s = of_read_number(range + na + pna, ns); - da = of_read_number(addr + 1, na - 1); - - pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); - - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; + return of_bus_default_map(addr, range, na, ns, pna, fna); } -static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr + 1, offset, na - 1); -} #endif /* CONFIG_PCI */ /* @@ -323,29 +298,13 @@ static void of_bus_isa_count_cells(struct device_node *child, } static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, - int pna) + int pna, int fna) { - u64 cp, s, da; - /* Check address type match */ if ((addr[0] ^ range[0]) & cpu_to_be32(1)) return OF_BAD_ADDR; - /* Read address values, skipping high cell */ - cp = of_read_number(range + 1, na - 1); - s = of_read_number(range + na + pna, ns); - da = of_read_number(addr + 1, na - 1); - - pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); - - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; -} - -static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr + 1, offset, na - 1); + return of_bus_default_map(addr, range, na, ns, pna, fna); } static unsigned int of_bus_isa_get_flags(const __be32 *addr) @@ -378,8 +337,8 @@ static struct of_bus of_busses[] = { .match = of_bus_pci_match, .count_cells = of_bus_pci_count_cells, .map = of_bus_pci_map, - .translate = of_bus_pci_translate, - .has_flags = true, + .translate = of_bus_default_flags_translate, + .flag_cells = 1, .get_flags = of_bus_pci_get_flags, }, #endif /* CONFIG_PCI */ @@ -390,8 +349,8 @@ static struct of_bus of_busses[] = { .match = of_bus_isa_match, .count_cells = of_bus_isa_count_cells, .map = of_bus_isa_map, - .translate = of_bus_isa_translate, - .has_flags = true, + .translate = of_bus_default_flags_translate, + .flag_cells = 1, .get_flags = of_bus_isa_get_flags, }, /* Default with flags cell */ @@ -402,7 +361,7 @@ static struct of_bus of_busses[] = { .count_cells = of_bus_default_count_cells, .map = of_bus_default_flags_map, .translate = of_bus_default_flags_translate, - .has_flags = true, + .flag_cells = 1, .get_flags = of_bus_default_flags_get_flags, }, /* Default */ @@ -495,7 +454,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, rlen /= 4; rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { - offset = bus->map(addr, ranges, na, ns, pna); + offset = bus->map(addr, ranges, na, ns, pna, bus->flag_cells); if (offset != OF_BAD_ADDR) break; } @@ -835,7 +794,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, int na = parser->na; int ns = parser->ns; int np = parser->pna + na + ns; - int busflag_na = 0; + int busflag_na = parser->bus->flag_cells; if (!range) return NULL; @@ -845,10 +804,6 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, range->flags = parser->bus->get_flags(parser->range); - /* A extra cell for resource flags */ - if (parser->bus->has_flags) - busflag_na = 1; - range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); if (parser->dma) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index f235ab55b9..126d265aa7 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -273,7 +273,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node, dev->dev.dma_mask = &dev->dev.coherent_dma_mask; /* setup generic device info */ - device_set_node(&dev->dev, of_fwnode_handle(of_node_get(node))); + device_set_node(&dev->dev, of_fwnode_handle(node)); dev->dev.parent = parent ? : &platform_bus; dev->dev.platform_data = platform_data; if (bus_id) diff --git a/drivers/of/property.c b/drivers/of/property.c index cf8dacf3e3..885ee040ee 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -762,7 +762,9 @@ struct device_node *of_graph_get_port_parent(struct device_node *node) /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && node; depth--) { node = of_get_next_parent(node); - if (depth == 2 && !of_node_name_eq(node, "ports")) + if (depth == 2 && !of_node_name_eq(node, "ports") && + !of_node_name_eq(node, "in-ports") && + !of_node_name_eq(node, "out-ports")) break; } return node; @@ -1062,36 +1064,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode, return of_device_get_match_data(dev); } -static struct device_node *of_get_compat_node(struct device_node *np) -{ - of_node_get(np); - - while (np) { - if (!of_device_is_available(np)) { - of_node_put(np); - np = NULL; - } - - if (of_property_present(np, "compatible")) - break; - - np = of_get_next_parent(np); - } - - return np; -} - -static struct device_node *of_get_compat_node_parent(struct device_node *np) -{ - struct device_node *parent, *node; - - parent = of_get_parent(np); - node = of_get_compat_node(parent); - of_node_put(parent); - - return node; -} - static void of_link_to_phandle(struct device_node *con_np, struct device_node *sup_np) { @@ -1221,10 +1193,10 @@ static struct device_node *parse_##fname(struct device_node *np, \ * @parse_prop.prop_name: Name of property holding a phandle value * @parse_prop.index: For properties holding a list of phandles, this is the * index into the list + * @get_con_dev: If the consumer node containing the property is never converted + * to a struct device, implement this ops so fw_devlink can use it + * to find the true consumer. * @optional: Describes whether a supplier is mandatory or not - * @node_not_dev: The consumer node containing the property is never converted - * to a struct device. Instead, parse ancestor nodes for the - * compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are @@ -1235,15 +1207,15 @@ static struct device_node *parse_##fname(struct device_node *np, \ struct supplier_bindings { struct device_node *(*parse_prop)(struct device_node *np, const char *prop_name, int index); + struct device_node *(*get_con_dev)(struct device_node *np); bool optional; - bool node_not_dev; }; DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells") DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells") DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells") -DEFINE_SIMPLE_PROP(io_channels, "io-channel", "#io-channel-cells") +DEFINE_SIMPLE_PROP(io_channels, "io-channels", "#io-channel-cells") DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL) DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells") DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") @@ -1261,12 +1233,12 @@ DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) -DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL) DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells") DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells") DEFINE_SIMPLE_PROP(leds, "leds", NULL) DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) DEFINE_SIMPLE_PROP(panel, "panel", NULL) +DEFINE_SIMPLE_PROP(msi_parent, "msi-parent", "#msi-cells") DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") @@ -1326,6 +1298,17 @@ static struct device_node *parse_interrupts(struct device_node *np, return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np; } +static struct device_node *parse_remote_endpoint(struct device_node *np, + const char *prop_name, + int index) +{ + /* Return NULL for index > 0 to signify end of remote-endpoints. */ + if (!index || strcmp(prop_name, "remote-endpoint")) + return NULL; + + return of_graph_get_remote_port_parent(np); +} + static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_clocks, }, { .parse_prop = parse_interconnects, }, @@ -1350,12 +1333,16 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_pinctrl6, }, { .parse_prop = parse_pinctrl7, }, { .parse_prop = parse_pinctrl8, }, - { .parse_prop = parse_remote_endpoint, .node_not_dev = true, }, + { + .parse_prop = parse_remote_endpoint, + .get_con_dev = of_graph_get_port_parent, + }, { .parse_prop = parse_pwms, }, { .parse_prop = parse_resets, }, { .parse_prop = parse_leds, }, { .parse_prop = parse_backlight, }, { .parse_prop = parse_panel, }, + { .parse_prop = parse_msi_parent, }, { .parse_prop = parse_gpio_compat, }, { .parse_prop = parse_interrupts, }, { .parse_prop = parse_regulators, }, @@ -1400,8 +1387,8 @@ 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; - con_dev_np = s->node_not_dev - ? of_get_compat_node_parent(con_np) + con_dev_np = s->get_con_dev + ? s->get_con_dev(con_np) : of_node_get(con_np); matched = true; i++; diff --git a/drivers/of/unittest-data/overlay_bad_unresolved.dtso b/drivers/of/unittest-data/overlay_bad_unresolved.dtso index 3b75a53ae8..f34d8780d4 100644 --- a/drivers/of/unittest-data/overlay_bad_unresolved.dtso +++ b/drivers/of/unittest-data/overlay_bad_unresolved.dtso @@ -3,5 +3,5 @@ /plugin/; &this_label_does_not_exist { - status = "ok"; + status = "okay"; }; diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi index bc0029cbf8..3344f15c37 100644 --- a/drivers/of/unittest-data/tests-address.dtsi +++ b/drivers/of/unittest-data/tests-address.dtsi @@ -51,5 +51,106 @@ }; }; + + address-tests2 { + #address-cells = <2>; + #size-cells = <1>; + + ranges = <0x10000000 0x01000000 0xa0000000 0x01000000>, + <0x10000000 0x02000000 0xb0000000 0x01000000>, + <0x20000000 0x01000000 0xc0000000 0x01000000>, + <0x20000000 0x02000000 0xd0000000 0x01000000>, + <0x00000000 0xd1000000 0xd1000000 0x01000000>, + <0x00000000 0xe8000000 0xe8000000 0x07f00000>, + <0x00000000 0xefff0000 0xefff0000 0x00010000>; + + bus-2cell@10000000 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x100000 0x10000 0x10000000 0x1a00000 0x10000>, + <0x100000 0x20000 0x10000000 0x1b00000 0x10000>, + <0x200000 0x10000 0x20000000 0x1c00000 0x10000>, + <0x200000 0x20000 0x20000000 0x2d00000 0x10000>; + + device@100000 { + reg = <0x100000 0x11000 0x100>, + <0x100000 0x12000 0x100>, + <0x200000 0x11000 0x100>, + <0x200000 0x21000 0x100>; + }; + }; + + bus-3cell@20000000 { + #address-cells = <3>; + #size-cells = <1>; + ranges = <0x1 0x100000 0x10000 0x10000000 0x1a00000 0x10000>, + <0x2 0x100000 0x10000 0x10000000 0x1b00000 0x10000>, + <0x3 0x200000 0x10000 0x20000000 0x1c00000 0x10000>, + <0x4 0x200000 0x20000 0x20000000 0x2d00000 0x10000>; + + local-bus@100000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xf1000000 0x1 0x100000 0x10000 0x10000>, + <0xf2000000 0x2 0x100000 0x10000 0x10000>, + <0xf3000000 0x3 0x200000 0x10000 0x08000>, + <0xf3800000 0x3 0x200000 0x18000 0x08000>, + <0xf4000000 0x4 0x200000 0x20000 0x10000>; + + device@f1001000 { + reg = <0xf1001000 0x100>, + <0xf2002000 0x100>, + <0xf3001000 0x100>, + <0xf3801000 0x100>, + <0xf4001000 0x100>; + }; + }; + }; + + pcie@d1070000 { + #address-cells = <0x03>; + #size-cells = <0x02>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x7f00000>, + <0x81000000 0 0x00000000 0 0xefff0000 0 0x0010000>; + reg = <0x00000000 0xd1070000 0x20000>; + + pci@0,0 { + #address-cells = <0x03>; + #size-cells = <0x02>; + bus-range = <0x01 0x01>; + device_type = "pci"; + ranges = <0x82000000 0 0xe8000000 + 0x82000000 0 0xe8000000 + 0 0x4400000>; + reg = <0x00 0x00 0x00 0x00 0x00>; + + dev@0,0 { + #address-cells = <0x03>; + #size-cells = <0x02>; + ranges = <0 0 0 0x82010000 0 0xe8000000 0 0x2000000>, + <1 0 0 0x82010000 0 0xea000000 0 0x1000000>, + <2 0 0 0x82010000 0 0xeb000000 0 0x0800000>, + <3 0 0 0x82010000 0 0xeb800000 0 0x0800000>, + <4 0 0 0x82010000 0 0xec000000 0 0x0020000>, + <5 0 0 0x82010000 0 0xec020000 0 0x0002000>; + reg = <0x10000 0x00 0x00 0x00 0x00>; + + local-bus@0 { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0xa0000000 0 0 0 0x2000000>, + <0xb0000000 1 0 0 0x1000000>; + + dev@e0000000 { + reg = <0xa0001000 0x1000>, + <0xb0002000 0x2000>; + }; + }; + }; + }; + }; + }; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index f278def7ef..d7593bde2d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -50,6 +50,12 @@ static struct unittest_results { failed; \ }) +#ifdef CONFIG_OF_KOBJ +#define OF_KREF_READ(NODE) kref_read(&(NODE)->kobj.kref) +#else +#define OF_KREF_READ(NODE) 1 +#endif + /* * Expected message may have a message level other than KERN_INFO. * Print the expected message only if the current loglevel will allow @@ -570,7 +576,7 @@ static void __init of_unittest_parse_phandle_with_args_map(void) pr_err("missing testcase data\n"); return; } - prefs[i] = kref_read(&p[i]->kobj.kref); + prefs[i] = OF_KREF_READ(p[i]); } rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); @@ -693,9 +699,9 @@ static void __init of_unittest_parse_phandle_with_args_map(void) unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); for (i = 0; i < ARRAY_SIZE(p); ++i) { - unittest(prefs[i] == kref_read(&p[i]->kobj.kref), + unittest(prefs[i] == OF_KREF_READ(p[i]), "provider%d: expected:%d got:%d\n", - i, prefs[i], kref_read(&p[i]->kobj.kref)); + i, prefs[i], OF_KREF_READ(p[i])); of_node_put(p[i]); } } @@ -1198,6 +1204,82 @@ static void __init of_unittest_reg(void) of_node_put(np); } +struct of_unittest_expected_res { + int index; + struct resource res; +}; + +static void __init of_unittest_check_addr(const char *node_path, + const struct of_unittest_expected_res *tab_exp, + unsigned int tab_exp_count) +{ + const struct of_unittest_expected_res *expected; + struct device_node *np; + struct resource res; + unsigned int count; + int ret; + + if (!IS_ENABLED(CONFIG_OF_ADDRESS)) + return; + + np = of_find_node_by_path(node_path); + if (!np) { + pr_err("missing testcase data (%s)\n", node_path); + return; + } + + expected = tab_exp; + count = tab_exp_count; + while (count--) { + ret = of_address_to_resource(np, expected->index, &res); + unittest(!ret, "of_address_to_resource(%pOF, %d) returned error %d\n", + np, expected->index, ret); + unittest(resource_type(&res) == resource_type(&expected->res) && + res.start == expected->res.start && + resource_size(&res) == resource_size(&expected->res), + "of_address_to_resource(%pOF, %d) wrong resource %pR, expected %pR\n", + np, expected->index, &res, &expected->res); + expected++; + } + + of_node_put(np); +} + +static const struct of_unittest_expected_res of_unittest_reg_2cell_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xa0a01000, 0x100) }, + {.index = 1, .res = DEFINE_RES_MEM(0xa0a02000, 0x100) }, + {.index = 2, .res = DEFINE_RES_MEM(0xc0c01000, 0x100) }, + {.index = 3, .res = DEFINE_RES_MEM(0xd0d01000, 0x100) }, +}; + +static const struct of_unittest_expected_res of_unittest_reg_3cell_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xa0a01000, 0x100) }, + {.index = 1, .res = DEFINE_RES_MEM(0xa0b02000, 0x100) }, + {.index = 2, .res = DEFINE_RES_MEM(0xc0c01000, 0x100) }, + {.index = 3, .res = DEFINE_RES_MEM(0xc0c09000, 0x100) }, + {.index = 4, .res = DEFINE_RES_MEM(0xd0d01000, 0x100) }, +}; + +static const struct of_unittest_expected_res of_unittest_reg_pci_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xe8001000, 0x1000) }, + {.index = 1, .res = DEFINE_RES_MEM(0xea002000, 0x2000) }, +}; + +static void __init of_unittest_translate_addr(void) +{ + of_unittest_check_addr("/testcase-data/address-tests2/bus-2cell@10000000/device@100000", + of_unittest_reg_2cell_expected_res, + ARRAY_SIZE(of_unittest_reg_2cell_expected_res)); + + of_unittest_check_addr("/testcase-data/address-tests2/bus-3cell@20000000/local-bus@100000/device@f1001000", + of_unittest_reg_3cell_expected_res, + ARRAY_SIZE(of_unittest_reg_3cell_expected_res)); + + of_unittest_check_addr("/testcase-data/address-tests2/pcie@d1070000/pci@0,0/dev@0,0/local-bus@0/dev@e0000000", + of_unittest_reg_pci_expected_res, + ARRAY_SIZE(of_unittest_reg_pci_expected_res)); +} + static void __init of_unittest_parse_interrupts(void) { struct device_node *np; @@ -4046,6 +4128,7 @@ static int __init of_unittest(void) of_unittest_bus_ranges(); of_unittest_bus_3cell_ranges(); of_unittest_reg(); + of_unittest_translate_addr(); of_unittest_match_node(); of_unittest_platform_populate(); of_unittest_overlay(); -- cgit v1.2.3