From: Sakari Ailus sakari.ailus@linux.intel.com
[ Upstream commit d9f866b2bb3eec38b3734f1fed325ec7c55ccdfa ]
fwnode_graph_get_next_subnode() may return fwnode backed by ACPI device nodes and there has been no check these devices are present in the system, unlike there has been on fwnode OF backend.
In order to provide consistent behaviour towards callers, add a check for device presence by introducing a new function acpi_get_next_present_subnode(), used as the get_next_child_node() fwnode operation that also checks device node presence.
Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Reviewed-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com Reviewed-by: Jonathan Cameron jonathan.cameron@huawei.com Link: https://patch.msgid.link/20251001102636.1272722-2-sakari.ailus@linux.intel.c... [ rjw: Kerneldoc comment and changelog edits ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES – this change fixes a real behavioural bug in the ACPI fwnode backend and should go to stable.
- `drivers/acpi/property.c:1375` adds `acpi_get_next_present_subnode()` so `.get_next_child_node` skips ACPI child devices whose `_STA` says they are absent (`acpi_device_is_present()`), while still returning data subnodes unchanged. - The new helper is now wired into the ACPI fwnode ops (`drivers/acpi/property.c:1731`), making generic helpers such as `fwnode_get_next_child_node()` and macros like `fwnode_for_each_child_node` (`include/linux/property.h:167`) behave the same as the OF backend, which already filtered unavailable children via `of_get_next_available_child()` (`drivers/of/property.c:1070`). - Several core helpers assume disabled endpoints never surface: e.g. `fwnode_graph_get_endpoint_by_id()` in `drivers/base/property.c:1286` promises to hide endpoints on disabled devices, and higher layers such as `v4l2_fwnode_reference_get_int_prop()` (`drivers/media/v4l2-core/v4l2-fwnode.c:1064`) iterate child nodes without rechecking availability. On ACPI systems today they still see powered-off devices, leading to asynchronous notifiers that wait forever for hardware that can’t appear, or to bogus graph enumerations. This patch closes that gap.
Risk is low: it only suppresses ACPI device nodes already known to be absent, aligns behaviour with DT userspace expectations, and leaves data nodes untouched. No extra dependencies are required, so the fix is self- contained and appropriate for stable backporting. Suggest running existing ACPI graph users (media/typec drivers) after backport to confirm no regressions.
drivers/acpi/property.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index c086786fe84cb..d74678f0ba4af 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -1357,6 +1357,28 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode, return NULL; }
+/* + * acpi_get_next_present_subnode - Return the next present child node handle + * @fwnode: Firmware node to find the next child node for. + * @child: Handle to one of the device's child nodes or a null handle. + * + * Like acpi_get_next_subnode(), but the device nodes returned by + * acpi_get_next_present_subnode() are guaranteed to be present. + * + * Returns: The fwnode handle of the next present sub-node. + */ +static struct fwnode_handle * +acpi_get_next_present_subnode(const struct fwnode_handle *fwnode, + struct fwnode_handle *child) +{ + do { + child = acpi_get_next_subnode(fwnode, child); + } while (is_acpi_device_node(child) && + !acpi_device_is_present(to_acpi_device_node(child))); + + return child; +} + /** * acpi_node_get_parent - Return parent fwnode of this fwnode * @fwnode: Firmware node whose parent to get @@ -1701,7 +1723,7 @@ static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode, .property_read_string_array = \ acpi_fwnode_property_read_string_array, \ .get_parent = acpi_node_get_parent, \ - .get_next_child_node = acpi_get_next_subnode, \ + .get_next_child_node = acpi_get_next_present_subnode, \ .get_named_child_node = acpi_fwnode_get_named_child_node, \ .get_name = acpi_fwnode_get_name, \ .get_name_prefix = acpi_fwnode_get_name_prefix, \