ACPI: utils: Add api to read _SUB from ACPI
authorStefan Binding <sbinding@opensource.cirrus.com>
Thu, 7 Jul 2022 15:10:36 +0000 (16:10 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 15 Jul 2022 11:35:09 +0000 (12:35 +0100)
Add a wrapper function to read the _SUB string from ACPI.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/20220707151037.3901050-2-sbinding@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/acpi/utils.c
include/linux/acpi.h

index 3a9773a09e199ad884b7954e1dfb24812937ed2a..5a7b8065e77ffd73f4d1b339571fc5e12d9d58f7 100644 (file)
@@ -291,6 +291,44 @@ int acpi_get_local_address(acpi_handle handle, u32 *addr)
 }
 EXPORT_SYMBOL(acpi_get_local_address);
 
+#define ACPI_MAX_SUB_BUF_SIZE  9
+
+const char *acpi_get_subsystem_id(acpi_handle handle)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       const char *sub;
+       size_t len;
+
+       status = acpi_evaluate_object(handle, METHOD_NAME__SUB, NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_debug(handle, "Reading ACPI _SUB failed: %#x\n", status);
+               return ERR_PTR(-ENODATA);
+       }
+
+       obj = buffer.pointer;
+       if (obj->type == ACPI_TYPE_STRING) {
+               len = strlen(obj->string.pointer);
+               if (len < ACPI_MAX_SUB_BUF_SIZE && len > 0) {
+                       sub = kstrdup(obj->string.pointer, GFP_KERNEL);
+                       if (!sub)
+                               sub = ERR_PTR(-ENOMEM);
+               } else {
+                       acpi_handle_err(handle, "ACPI _SUB Length %zu is Invalid\n", len);
+                       sub = ERR_PTR(-ENODATA);
+               }
+       } else {
+               acpi_handle_warn(handle, "Warning ACPI _SUB did not return a string\n");
+               sub = ERR_PTR(-ENODATA);
+       }
+
+       acpi_os_free(buffer.pointer);
+
+       return sub;
+}
+EXPORT_SYMBOL_GPL(acpi_get_subsystem_id);
+
 acpi_status
 acpi_evaluate_reference(acpi_handle handle,
                        acpi_string pathname,
index 4f82a5bc6d987fe9ef1f6ddfb253d9ba0e087fc2..968a187f14f0079c2f4692732e2fad6381b24033 100644 (file)
@@ -762,6 +762,7 @@ static inline u64 acpi_arch_get_root_pointer(void)
 #endif
 
 int acpi_get_local_address(acpi_handle handle, u32 *addr);
+const char *acpi_get_subsystem_id(acpi_handle handle);
 
 #else  /* !CONFIG_ACPI */
 
@@ -1023,6 +1024,11 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
        return -ENODEV;
 }
 
+static inline const char *acpi_get_subsystem_id(acpi_handle handle)
+{
+       return ERR_PTR(-ENODEV);
+}
+
 static inline int acpi_register_wakeup_handler(int wake_irq,
        bool (*wakeup)(void *context), void *context)
 {