Skip to content

Commit 8661423

Browse files
jwrdegoederafaeljw
authored andcommitted
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>
1 parent 4f7d029 commit 8661423

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

drivers/acpi/utils.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,72 @@ bool acpi_dev_found(const char *hid)
736736
}
737737
EXPORT_SYMBOL(acpi_dev_found);
738738

739+
struct acpi_dev_present_info {
740+
struct acpi_device_id hid[2];
741+
const char *uid;
742+
s64 hrv;
743+
};
744+
745+
static 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+
*/
789+
bool 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+
}
803+
EXPORT_SYMBOL(acpi_dev_present);
804+
739805
/*
740806
* acpi_backlight= handling, this is done here rather then in video_detect.c
741807
* because __setup cannot be used in modules.

include/acpi/acpi_bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
8888
}
8989

9090
bool acpi_dev_found(const char *hid);
91+
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
9192

9293
#ifdef CONFIG_ACPI
9394

include/linux/acpi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,11 @@ static inline bool acpi_dev_found(const char *hid)
611611
return false;
612612
}
613613

614+
static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
615+
{
616+
return false;
617+
}
618+
614619
static inline bool is_acpi_node(struct fwnode_handle *fwnode)
615620
{
616621
return false;

0 commit comments

Comments
 (0)