drm/i915/gt: Fix a double free in gen8_preallocate_top_level_pdp
[linux-2.6-microblaze.git] / drivers / of / property.c
index 5f9eed7..5036a36 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/of_irq.h>
 #include <linux/string.h>
 #include <linux/moduleparam.h>
 
@@ -1102,7 +1103,9 @@ static int of_link_to_phandle(struct device_node *con_np,
         * created for them.
         */
        sup_dev = get_dev_from_fwnode(&sup_np->fwnode);
-       if (!sup_dev && of_node_check_flag(sup_np, OF_POPULATED)) {
+       if (!sup_dev &&
+           (of_node_check_flag(sup_np, OF_POPULATED) ||
+            sup_np->fwnode.flags & FWNODE_FLAG_NOT_DEVICE)) {
                pr_debug("Not linking %pOFP to %pOFP - No struct device\n",
                         con_np, sup_np);
                of_node_put(sup_np);
@@ -1232,6 +1235,7 @@ 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);
+       bool optional;
 };
 
 DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells")
@@ -1244,8 +1248,6 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
 DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
 DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells")
 DEFINE_SIMPLE_PROP(extcon, "extcon", NULL)
-DEFINE_SIMPLE_PROP(interrupts_extended, "interrupts-extended",
-                                       "#interrupt-cells")
 DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL)
 DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells")
 DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL)
@@ -1271,19 +1273,55 @@ static struct device_node *parse_iommu_maps(struct device_node *np,
        return of_parse_phandle(np, prop_name, (index * 4) + 1);
 }
 
+static struct device_node *parse_gpio_compat(struct device_node *np,
+                                            const char *prop_name, int index)
+{
+       struct of_phandle_args sup_args;
+
+       if (strcmp(prop_name, "gpio") && strcmp(prop_name, "gpios"))
+               return NULL;
+
+       /*
+        * Ignore node with gpio-hog property since its gpios are all provided
+        * by its parent.
+        */
+       if (of_find_property(np, "gpio-hog", NULL))
+               return NULL;
+
+       if (of_parse_phandle_with_args(np, prop_name, "#gpio-cells", index,
+                                      &sup_args))
+               return NULL;
+
+       return sup_args.np;
+}
+
+static struct device_node *parse_interrupts(struct device_node *np,
+                                           const char *prop_name, int index)
+{
+       struct of_phandle_args sup_args;
+
+       if (!IS_ENABLED(CONFIG_OF_IRQ) || IS_ENABLED(CONFIG_PPC))
+               return NULL;
+
+       if (strcmp(prop_name, "interrupts") &&
+           strcmp(prop_name, "interrupts-extended"))
+               return NULL;
+
+       return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np;
+}
+
 static const struct supplier_bindings of_supplier_bindings[] = {
        { .parse_prop = parse_clocks, },
        { .parse_prop = parse_interconnects, },
-       { .parse_prop = parse_iommus, },
-       { .parse_prop = parse_iommu_maps, },
+       { .parse_prop = parse_iommus, .optional = true, },
+       { .parse_prop = parse_iommu_maps, .optional = true, },
        { .parse_prop = parse_mboxes, },
        { .parse_prop = parse_io_channels, },
        { .parse_prop = parse_interrupt_parent, },
-       { .parse_prop = parse_dmas, },
+       { .parse_prop = parse_dmas, .optional = true, },
        { .parse_prop = parse_power_domains, },
        { .parse_prop = parse_hwlocks, },
        { .parse_prop = parse_extcon, },
-       { .parse_prop = parse_interrupts_extended, },
        { .parse_prop = parse_nvmem_cells, },
        { .parse_prop = parse_phys, },
        { .parse_prop = parse_wakeup_parent, },
@@ -1296,6 +1334,8 @@ static const struct supplier_bindings of_supplier_bindings[] = {
        { .parse_prop = parse_pinctrl6, },
        { .parse_prop = parse_pinctrl7, },
        { .parse_prop = parse_pinctrl8, },
+       { .parse_prop = parse_gpio_compat, },
+       { .parse_prop = parse_interrupts, },
        { .parse_prop = parse_regulators, },
        { .parse_prop = parse_gpio, },
        { .parse_prop = parse_gpios, },
@@ -1332,6 +1372,11 @@ static int of_link_property(struct device_node *con_np, const char *prop_name)
 
        /* Do not stop at first failed link, link all available suppliers. */
        while (!matched && s->parse_prop) {
+               if (s->optional && !fw_devlink_is_strict()) {
+                       s++;
+                       continue;
+               }
+
                while ((phandle = s->parse_prop(con_np, prop_name, i))) {
                        matched = true;
                        i++;