summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorDaniel Scally <djrscally@gmail.com>2022-09-22 00:04:35 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2022-09-24 19:12:32 +0200
commitcca8a7efea6402f463239a1bb337d01b0cad7b2e (patch)
treeeb7ce6efbf056a9a0703df30358d8c15f60390b4 /drivers/acpi
parent98378956a407392109817278c6edd464252c7a83 (diff)
ACPI: scan: Add acpi_dev_get_next_consumer_dev()
In commit b83e2b306736 ("ACPI: scan: Add function to fetch dependent of ACPI device") we added a means of fetching the first device to declare itself dependent on another ACPI device in the _DEP method. One assumption in that patch was that there would only be a single consuming device, but this has not held. Replace that function with a new function that fetches the next consumer of a supplier device. Where no "previous" consumer is passed in, it behaves identically to the original function. Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Daniel Scally <djrscally@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/scan.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6b9ea937de1..d0277427e7ee 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2235,9 +2235,22 @@ ok:
return 0;
}
-static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
+static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
{
- struct acpi_device *adev;
+ struct acpi_device **adev_p = data;
+ struct acpi_device *adev = *adev_p;
+
+ /*
+ * If we're passed a 'previous' consumer device then we need to skip
+ * any consumers until we meet the previous one, and then NULL @data
+ * so the next one can be returned.
+ */
+ if (adev) {
+ if (dep->consumer == adev->handle)
+ *adev_p = NULL;
+
+ return 0;
+ }
adev = acpi_get_acpi_dev(dep->consumer);
if (adev) {
@@ -2368,25 +2381,32 @@ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
/**
- * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
+ * acpi_dev_get_next_consumer_dev - Return the next adev dependent on @supplier
* @supplier: Pointer to the dependee device
+ * @start: Pointer to the current dependent device
*
- * Returns the first &struct acpi_device which declares itself dependent on
+ * Returns the next &struct acpi_device which declares itself dependent on
* @supplier via the _DEP buffer, parsed from the acpi_dep_list.
*
- * The caller is responsible for putting the reference to adev when it is no
- * longer needed.
+ * If the returned adev is not passed as @start to this function, the caller is
+ * responsible for putting the reference to adev when it is no longer needed.
*/
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier)
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+ struct acpi_device *start)
{
- struct acpi_device *adev = NULL;
+ struct acpi_device *adev = start;
acpi_walk_dep_device_list(supplier->handle,
- acpi_dev_get_first_consumer_dev_cb, &adev);
+ acpi_dev_get_next_consumer_dev_cb, &adev);
+
+ acpi_dev_put(start);
+
+ if (adev == start)
+ return NULL;
return adev;
}
-EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev);
+EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
/**
* acpi_bus_scan - Add ACPI device node objects in a given namespace scope.