summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-11-30 14:47:13 -0600
committerBjorn Helgaas <helgaas@kernel.org>2016-12-01 14:59:32 -0600
commit00710984eac523ffed4e92850511d7610cfe908b (patch)
tree65b78c486753503d73a6faa02d07f577667a7a41 /drivers
parent1001354ca34179f3db924eb66672442a173147dc (diff)
downloadlinux-00710984eac523ffed4e92850511d7610cfe908b.tar.bz2
ACPI: Add acpi_resource_consumer() to find device that claims a resource
Add acpi_resource_consumer(). This takes a struct resource and searches the ACPI namespace for a device whose current resource settings (_CRS) includes the resource. It returns the device if it exists, or NULL if no device uses the resource. If more than one device uses the resource (this may happen in the case of bridges), acpi_resource_consumer() returns the first one found by acpi_get_devices() in its modified depth-first walk of the namespace. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/resource.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 56241eb341f4..cb57962ef7c4 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -664,3 +664,60 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
return (type & types) ? 0 : 1;
}
EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
+
+static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
+{
+ struct list_head resource_list;
+ struct resource_entry *rentry;
+ int ret, found = 0;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+ if (ret < 0)
+ return 0;
+
+ list_for_each_entry(rentry, &resource_list, node) {
+ if (resource_contains(rentry->res, res)) {
+ found = 1;
+ break;
+ }
+
+ }
+
+ acpi_dev_free_resource_list(&resource_list);
+ return found;
+}
+
+static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
+ void *context, void **ret)
+{
+ struct resource *res = context;
+ struct acpi_device **consumer = (struct acpi_device **) ret;
+ struct acpi_device *adev;
+
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+
+ if (acpi_dev_consumes_res(adev, res)) {
+ *consumer = adev;
+ return AE_CTRL_TERMINATE;
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_resource_consumer - Find the ACPI device that consumes @res.
+ * @res: Resource to search for.
+ *
+ * Search the current resource settings (_CRS) of every ACPI device node
+ * for @res. If we find an ACPI device whose _CRS includes @res, return
+ * it. Otherwise, return NULL.
+ */
+struct acpi_device *acpi_resource_consumer(struct resource *res)
+{
+ struct acpi_device *consumer = NULL;
+
+ acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);
+ return consumer;
+}