Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

of: property: fw_devlink: Add support for remote-endpoint

remote-endpoint property seems to always come in pairs where two devices
point to each other. So, we can't really tell from DT if there is a
functional probe order dependency between these two devices.

However, there can be other dependencies between two devices that point
to each other with remote-endpoint. This non-remote-endpoint dependency
combined with one of the remote-endpoint dependency can lead to a cyclic
dependency[1].

To avoid this cyclic dependency from incorrectly blocking probes,
fw_devlink needs to be made aware of remote-endpoint dependencies even
though remote-endpoint dependencies by themselves won't affect probe
ordering (because fw_devlink will see the cyclic dependency between
remote-endpoint devices and ignore the dependencies that cause the
cycle).

Also, if a device ever needs to know if a non-probe-blocking
remote-endpoint has finished probing, it can now use the sync_state() to
figure it out.

[1] - https://lore.kernel.org/lkml/CAGETcx9Snf23wrXqjDhJiTok9M3GcoVYDSyNYSMj9QnSRrA=cA@mail.gmail.com/#t

Fixes: ea718c699055 ("Revert "Revert "driver core: Set fw_devlink=on by default""")
Reported-by: Stephen Boyd <swboyd@chromium.org>
Tested-by: Stephen Boyd <swboyd@chromium.org>
Signed-off-by: Saravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20210330185056.1022008-1-saravanak@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Saravana Kannan and committed by
Greg Kroah-Hartman
f7514a66 ed7027fd

+32 -16
+32 -16
drivers/of/property.c
··· 1038 1038 return false; 1039 1039 } 1040 1040 1041 + static struct device_node *of_get_compat_node(struct device_node *np) 1042 + { 1043 + of_node_get(np); 1044 + 1045 + while (np) { 1046 + if (!of_device_is_available(np)) { 1047 + of_node_put(np); 1048 + np = NULL; 1049 + } 1050 + 1051 + if (of_find_property(np, "compatible", NULL)) 1052 + break; 1053 + 1054 + np = of_get_next_parent(np); 1055 + } 1056 + 1057 + return np; 1058 + } 1059 + 1041 1060 /** 1042 1061 * of_link_to_phandle - Add fwnode link to supplier from supplier phandle 1043 1062 * @con_np: consumer device tree node ··· 1080 1061 struct device *sup_dev; 1081 1062 struct device_node *tmp_np = sup_np; 1082 1063 1083 - of_node_get(sup_np); 1084 1064 /* 1085 1065 * Find the device node that contains the supplier phandle. It may be 1086 1066 * @sup_np or it may be an ancestor of @sup_np. 1087 1067 */ 1088 - while (sup_np) { 1089 - 1090 - /* Don't allow linking to a disabled supplier */ 1091 - if (!of_device_is_available(sup_np)) { 1092 - of_node_put(sup_np); 1093 - sup_np = NULL; 1094 - } 1095 - 1096 - if (of_find_property(sup_np, "compatible", NULL)) 1097 - break; 1098 - 1099 - sup_np = of_get_next_parent(sup_np); 1100 - } 1101 - 1068 + sup_np = of_get_compat_node(sup_np); 1102 1069 if (!sup_np) { 1103 1070 pr_debug("Not linking %pOFP to %pOFP - No device\n", 1104 1071 con_np, tmp_np); ··· 1230 1225 * @parse_prop.prop_name: Name of property holding a phandle value 1231 1226 * @parse_prop.index: For properties holding a list of phandles, this is the 1232 1227 * index into the list 1228 + * @optional: The property can be an optional dependency. 1229 + * @node_not_dev: The consumer node containing the property is never a device. 1233 1230 * 1234 1231 * Returns: 1235 1232 * parse_prop() return values are ··· 1243 1236 struct device_node *(*parse_prop)(struct device_node *np, 1244 1237 const char *prop_name, int index); 1245 1238 bool optional; 1239 + bool node_not_dev; 1246 1240 }; 1247 1241 1248 1242 DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") ··· 1268 1260 DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) 1269 1261 DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) 1270 1262 DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) 1263 + DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL) 1271 1264 DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) 1272 1265 DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") 1273 1266 DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") ··· 1343 1334 { .parse_prop = parse_pinctrl6, }, 1344 1335 { .parse_prop = parse_pinctrl7, }, 1345 1336 { .parse_prop = parse_pinctrl8, }, 1337 + { .parse_prop = parse_remote_endpoint, .node_not_dev = true, }, 1346 1338 { .parse_prop = parse_gpio_compat, }, 1347 1339 { .parse_prop = parse_interrupts, }, 1348 1340 { .parse_prop = parse_regulators, }, ··· 1388 1378 } 1389 1379 1390 1380 while ((phandle = s->parse_prop(con_np, prop_name, i))) { 1381 + struct device_node *con_dev_np; 1382 + 1383 + con_dev_np = s->node_not_dev 1384 + ? of_get_compat_node(con_np) 1385 + : of_node_get(con_np); 1391 1386 matched = true; 1392 1387 i++; 1393 - of_link_to_phandle(con_np, phandle); 1388 + of_link_to_phandle(con_dev_np, phandle); 1394 1389 of_node_put(phandle); 1390 + of_node_put(con_dev_np); 1395 1391 } 1396 1392 s++; 1397 1393 }