summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-11-30 15:47:13 -0500
committerBjorn Helgaas <helgaas@kernel.org>2016-12-01 15:59:32 -0500
commit00710984eac523ffed4e92850511d7610cfe908b (patch)
tree65b78c486753503d73a6faa02d07f577667a7a41
parent1001354ca34179f3db924eb66672442a173147dc (diff)
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>
-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,
664 return (type & types) ? 0 : 1; 664 return (type & types) ? 0 : 1;
665} 665}
666EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); 666EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
667
668static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
669{
670 struct list_head resource_list;
671 struct resource_entry *rentry;
672 int ret, found = 0;
673
674 INIT_LIST_HEAD(&resource_list);
675 ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
676 if (ret < 0)
677 return 0;
678
679 list_for_each_entry(rentry, &resource_list, node) {
680 if (resource_contains(rentry->res, res)) {
681 found = 1;
682 break;
683 }
684
685 }
686
687 acpi_dev_free_resource_list(&resource_list);
688 return found;
689}
690
691static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
692 void *context, void **ret)
693{
694 struct resource *res = context;
695 struct acpi_device **consumer = (struct acpi_device **) ret;
696 struct acpi_device *adev;
697
698 if (acpi_bus_get_device(handle, &adev))
699 return AE_OK;
700
701 if (acpi_dev_consumes_res(adev, res)) {
702 *consumer = adev;
703 return AE_CTRL_TERMINATE;
704 }
705
706 return AE_OK;
707}
708
709/**
710 * acpi_resource_consumer - Find the ACPI device that consumes @res.
711 * @res: Resource to search for.
712 *
713 * Search the current resource settings (_CRS) of every ACPI device node
714 * for @res. If we find an ACPI device whose _CRS includes @res, return
715 * it. Otherwise, return NULL.
716 */
717struct acpi_device *acpi_resource_consumer(struct resource *res)
718{
719 struct acpi_device *consumer = NULL;
720
721 acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);
722 return consumer;
723}
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,
419 return acpi_dev_filter_resource_type(ares, (unsigned long)arg); 419 return acpi_dev_filter_resource_type(ares, (unsigned long)arg);
420} 420}
421 421
422struct acpi_device *acpi_resource_consumer(struct resource *res);
423
422int acpi_check_resource_conflict(const struct resource *res); 424int acpi_check_resource_conflict(const struct resource *res);
423 425
424int acpi_check_region(resource_size_t start, resource_size_t n, 426int 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)
762 return -EINVAL; 764 return -EINVAL;
763} 765}
764 766
767static inline struct acpi_device *acpi_resource_consumer(struct resource *res)
768{
769 return NULL;
770}
771
765#endif /* !CONFIG_ACPI */ 772#endif /* !CONFIG_ACPI */
766 773
767#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC 774#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC