return FIND_CHILD_MAX_SCORE;
 }
 
-struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
-                                          u64 address, bool check_children)
+struct find_child_walk_data {
+       struct acpi_device *adev;
+       u64 address;
+       int score;
+       bool check_children;
+};
+
+static int check_one_child(struct acpi_device *adev, void *data)
 {
-       struct acpi_device *adev, *ret = NULL;
-       int ret_score = 0;
+       struct find_child_walk_data *wd = data;
+       int score;
 
-       if (!parent)
-               return NULL;
+       if (!adev->pnp.type.bus_address || acpi_device_adr(adev) != wd->address)
+               return 0;
 
-       list_for_each_entry(adev, &parent->children, node) {
-               acpi_bus_address addr = acpi_device_adr(adev);
-               int score;
+       if (!wd->adev) {
+               /* This is the first matching object.  Save it and continue. */
+               wd->adev = adev;
+               return 0;
+       }
 
-               if (!adev->pnp.type.bus_address || addr != address)
-                       continue;
+       /*
+        * There is more than one matching device object with the same _ADR
+        * value.  That really is unexpected, so we are kind of beyond the scope
+        * of the spec here.  We have to choose which one to return, though.
+        *
+        * First, get the score for the previously found object and terminate
+        * the walk if it is maximum.
+       */
+       if (!wd->score) {
+               score = find_child_checks(wd->adev, wd->check_children);
+               if (score == FIND_CHILD_MAX_SCORE)
+                       return 1;
+
+               wd->score = score;
+       }
+       /*
+        * Second, if the object that has just been found has a better score,
+        * replace the previously found one with it and terminate the walk if
+        * the new score is maximum.
+        */
+       score = find_child_checks(adev, wd->check_children);
+       if (score > wd->score) {
+               wd->adev = adev;
+               if (score == FIND_CHILD_MAX_SCORE)
+                       return 1;
 
-               if (!ret) {
-                       /* This is the first matching object.  Save it. */
-                       ret = adev;
-                       continue;
-               }
-               /*
-                * There is more than one matching device object with the same
-                * _ADR value.  That really is unexpected, so we are kind of
-                * beyond the scope of the spec here.  We have to choose which
-                * one to return, though.
-                *
-                * First, check if the previously found object is good enough
-                * and return it if so.  Second, do the same for the object that
-                * we've just found.
-                */
-               if (!ret_score) {
-                       ret_score = find_child_checks(ret, check_children);
-                       if (ret_score == FIND_CHILD_MAX_SCORE)
-                               return ret;
-               }
-               score = find_child_checks(adev, check_children);
-               if (score == FIND_CHILD_MAX_SCORE) {
-                       return adev;
-               } else if (score > ret_score) {
-                       ret = adev;
-                       ret_score = score;
-               }
+               wd->score = score;
        }
-       return ret;
+
+       /* Continue, because there may be better matches. */
+       return 0;
+}
+
+struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
+                                          u64 address, bool check_children)
+{
+       struct find_child_walk_data wd = {
+               .address = address,
+               .check_children = check_children,
+               .adev = NULL,
+               .score = 0,
+       };
+
+       if (parent)
+               acpi_dev_for_each_child(parent, check_one_child, &wd);
+
+       return wd.adev;
 }
 EXPORT_SYMBOL_GPL(acpi_find_child_device);