aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/utils.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2017-04-19 08:02:08 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-04-19 16:53:34 -0400
commit8661423eea1a1b58417014716e3f1ba286072379 (patch)
tree686462c9b7444bbc6ae2eb338901deb356c2c98b /drivers/acpi/utils.c
parent4f7d029b9bf009fbee76bb10c0c4351a1870d2f3 (diff)
ACPI / utils: Add new acpi_dev_present helper
acpi_dev_found just iterates over all ACPI-ids and sees if one matches. This means that it will return true for devices which are in the DSDT but disabled (their _STA method returns 0). For some drivers it is useful to be able to check if a certain HID is not only present in the namespace, but also actually present as in acpi_device_is_present() will return true for the device. For example because if a certain device is present then the driver will want to use an extcon or IIO ADC channel provided by that device. This commit adds a new acpi_dev_present helper which drivers can use to this end. Like acpi_dev_found, acpi_dev_present take a HID as argument, but it also has 2 extra optional arguments to only check for an ACPI device with a specific UID and/or HRV value. This makes it more generic and allows it to replace custom code doing similar checks in several places. Arguably acpi_dev_present is what acpi_dev_found should have been, but there are too many users to just change acpi_dev_found without the risk of breaking something. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Lukas Wunner <lukas@wunner.de> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/utils.c')
-rw-r--r--drivers/acpi/utils.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 22c09952e177..27d0dcfcf47d 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -736,6 +736,72 @@ bool acpi_dev_found(const char *hid)
736} 736}
737EXPORT_SYMBOL(acpi_dev_found); 737EXPORT_SYMBOL(acpi_dev_found);
738 738
739struct acpi_dev_present_info {
740 struct acpi_device_id hid[2];
741 const char *uid;
742 s64 hrv;
743};
744
745static int acpi_dev_present_cb(struct device *dev, void *data)
746{
747 struct acpi_device *adev = to_acpi_device(dev);
748 struct acpi_dev_present_info *match = data;
749 unsigned long long hrv;
750 acpi_status status;
751
752 if (acpi_match_device_ids(adev, match->hid))
753 return 0;
754
755 if (match->uid && (!adev->pnp.unique_id ||
756 strcmp(adev->pnp.unique_id, match->uid)))
757 return 0;
758
759 if (match->hrv == -1)
760 return 1;
761
762 status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
763 if (ACPI_FAILURE(status))
764 return 0;
765
766 return hrv == match->hrv;
767}
768
769/**
770 * acpi_dev_present - Detect that a given ACPI device is present
771 * @hid: Hardware ID of the device.
772 * @uid: Unique ID of the device, pass NULL to not check _UID
773 * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
774 *
775 * Return %true if a matching device was present at the moment of invocation.
776 * Note that if the device is pluggable, it may since have disappeared.
777 *
778 * Note that unlike acpi_dev_found() this function checks the status
779 * of the device. So for devices which are present in the dsdt, but
780 * which are disabled (their _STA callback returns 0) this function
781 * will return false.
782 *
783 * For this function to work, acpi_bus_scan() must have been executed
784 * which happens in the subsys_initcall() subsection. Hence, do not
785 * call from a subsys_initcall() or earlier (use acpi_get_devices()
786 * instead). Calling from module_init() is fine (which is synonymous
787 * with device_initcall()).
788 */
789bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
790{
791 struct acpi_dev_present_info match = {};
792 struct device *dev;
793
794 strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
795 match.uid = uid;
796 match.hrv = hrv;
797
798 dev = bus_find_device(&acpi_bus_type, NULL, &match,
799 acpi_dev_present_cb);
800
801 return !!dev;
802}
803EXPORT_SYMBOL(acpi_dev_present);
804
739/* 805/*
740 * acpi_backlight= handling, this is done here rather then in video_detect.c 806 * acpi_backlight= handling, this is done here rather then in video_detect.c
741 * because __setup cannot be used in modules. 807 * because __setup cannot be used in modules.