[PATCH 6/7] ACPI: scan: Fix battery devices not working with acpi.defer_scan_based_on_dep=1

Hans de Goede
2020-11-21T20:31:09Z

When battery devices get added during the second step of the now 2 step
scan-process, then acpi_walk_dep_device_list() may have already been
called for some deps during the first step.

In this case acpi_device_dep_initialize() should not add these deps to
the acpi_dep_list; and it should not increase adev->dep_unmet.

Add a check for already registered (and bound to a driver) devices to
acpi_device_dep_initialize(). This fixes battery devices (which honor the
dep_unmet value) not working with acpi.defer_scan_based_on_dep=1.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/acpi/scan.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 9927036bfe77..44001610f6a4 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -17,6 +17,8 @@
#include <linux/platform_data/x86/apple.h>
#include <linux/pgtable.h>

+#include "acpica/accommon.h"
+#include "acpica/acnamesp.h"
#include "internal.h"

#define _COMPONENT ACPI_BUS_COMPONENT
@@ -1935,7 +1937,10 @@ static void acpi_device_dep_initialize(struct acpi_device *adev)
}

for (i = 0; i < dep_devices.count; i++) {
+ struct acpi_device *dep_adev = NULL;
+ struct acpi_namespace_node *node;
struct acpi_device_info *info;
+ struct device *dep_dev;
int skip;

status = acpi_get_object_info(dep_devices.handles[i], &info);
@@ -1950,6 +1955,30 @@ static void acpi_device_dep_initialize(struct acpi_device *adev)
if (skip)
continue;

+ /*
+ * Skip devices which already have a driver bound
+ * and thus are already available for use.
+ * We only need to do this during the second scan step,
+ * when acpi_check_defer_add == false.
+ */
+ if (!acpi_check_defer_add) {
+ /*
+ * Cannot call acpi_bus_get_device here as we are called
+ * with ACPI_MTX_NAMESPACE held.
+ */
+ node = acpi_ns_validate_handle(dep_devices.handles[i]);
+ if (!node)
+ continue; /* Should never happen */
+
+ status = acpi_ns_get_attached_data(node, acpi_scan_drop_device,
+ (void **)&dep_adev);
+ if (ACPI_SUCCESS(status) && dep_adev) {
+ dep_dev = acpi_get_first_physical_node(dep_adev);
+ if (dep_dev && dep_dev->driver)
+ continue;
+ }
+ }
+
dep = kzalloc(sizeof(struct acpi_dep_data), GFP_KERNEL);
if (!dep)
return;
--
2.28.0