summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/resource.c57
-rw-r--r--include/linux/acpi.h7
2 files changed, 64 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;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index ddbeda6dbdc8..b00ad73c946d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -419,6 +419,8 @@ static inline int acpi_dev_filter_resource_type_cb(struct acpi_resource *ares,
return acpi_dev_filter_resource_type(ares, (unsigned long)arg);
}
+struct acpi_device *acpi_resource_consumer(struct resource *res);
+
int acpi_check_resource_conflict(const struct resource *res);
int acpi_check_region(resource_size_t start, resource_size_t n,
@@ -762,6 +764,11 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb)
return -EINVAL;
}
+static inline struct acpi_device *acpi_resource_consumer(struct resource *res)
+{
+ return NULL;
+}
+
#endif /* !CONFIG_ACPI */
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC