diff options
Diffstat (limited to 'drivers/acpi/utils.c')
| -rw-r--r-- | drivers/acpi/utils.c | 512 |
1 files changed, 389 insertions, 123 deletions
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index b9d956c916f5..526563a0d188 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -1,24 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#define pr_fmt(fmt) "ACPI: utils: " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> @@ -31,24 +20,12 @@ #include "internal.h" #include "sleep.h" -#define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME("utils"); - /* -------------------------------------------------------------------------- Object Evaluation Helpers -------------------------------------------------------------------------- */ -static void -acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) -{ -#ifdef ACPI_DEBUG_OUTPUT - char prefix[80] = {'\0'}; - struct acpi_buffer buffer = {sizeof(prefix), prefix}; - acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", - (char *) prefix, p, acpi_format_exception(s))); -#else - return; -#endif +static void acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) +{ + acpi_handle_debug(h, "Evaluate [%s]: %s\n", p, acpi_format_exception(s)); } acpi_status @@ -66,25 +43,24 @@ acpi_extract_package(union acpi_object *package, if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) { - printk(KERN_WARNING PREFIX "Invalid package argument\n"); + pr_debug("Invalid package argument\n"); return AE_BAD_PARAMETER; } if (!format || !format->pointer || (format->length < 1)) { - printk(KERN_WARNING PREFIX "Invalid format argument\n"); + pr_debug("Invalid format argument\n"); return AE_BAD_PARAMETER; } if (!buffer) { - printk(KERN_WARNING PREFIX "Invalid buffer argument\n"); + pr_debug("Invalid buffer argument\n"); return AE_BAD_PARAMETER; } format_count = (format->length / sizeof(char)) - 1; if (format_count > package->package.count) { - printk(KERN_WARNING PREFIX "Format specifies more objects [%d]" - " than exist in package [%d].\n", - format_count, package->package.count); + pr_debug("Format specifies more objects [%d] than present [%d]\n", + format_count, package->package.count); return AE_BAD_DATA; } @@ -112,12 +88,9 @@ acpi_extract_package(union acpi_object *package, tail_offset += sizeof(char *); break; default: - printk(KERN_WARNING PREFIX "Invalid package element" - " [%d]: got number, expecting" - " [%c]\n", - i, format_string[i]); + pr_debug("Invalid package element [%d]: got number, expected [%c]\n", + i, format_string[i]); return AE_BAD_DATA; - break; } break; @@ -137,12 +110,9 @@ acpi_extract_package(union acpi_object *package, tail_offset += sizeof(u8 *); break; default: - printk(KERN_WARNING PREFIX "Invalid package element" - " [%d] got string/buffer," - " expecting [%c]\n", - i, format_string[i]); + pr_debug("Invalid package element [%d] got string/buffer, expected [%c]\n", + i, format_string[i]); return AE_BAD_DATA; - break; } break; case ACPI_TYPE_LOCAL_REFERENCE: @@ -152,23 +122,17 @@ acpi_extract_package(union acpi_object *package, tail_offset += sizeof(void *); break; default: - printk(KERN_WARNING PREFIX "Invalid package element" - " [%d] got reference," - " expecting [%c]\n", - i, format_string[i]); + pr_debug("Invalid package element [%d] got reference, expected [%c]\n", + i, format_string[i]); return AE_BAD_DATA; - break; } break; case ACPI_TYPE_PACKAGE: default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found unsupported element at index=%d\n", - i)); + pr_debug("Unsupported element at index=%d\n", i); /* TBD: handle nested packages... */ return AE_SUPPORT; - break; } } @@ -306,30 +270,88 @@ acpi_evaluate_integer(acpi_handle handle, *data = element.integer.value; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); + acpi_handle_debug(handle, "Return value [%llu]\n", *data); return AE_OK; } EXPORT_SYMBOL(acpi_evaluate_integer); -acpi_status -acpi_evaluate_reference(acpi_handle handle, - acpi_string pathname, - struct acpi_object_list *arguments, - struct acpi_handle_list *list) +int acpi_get_local_u64_address(acpi_handle handle, u64 *addr) +{ + acpi_status status; + + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, addr); + if (ACPI_FAILURE(status)) + return -ENODATA; + return 0; +} +EXPORT_SYMBOL(acpi_get_local_u64_address); + +int acpi_get_local_address(acpi_handle handle, u32 *addr) +{ + u64 adr; + int ret; + + ret = acpi_get_local_u64_address(handle, &adr); + if (ret < 0) + return ret; + *addr = (u32)adr; + return 0; +} +EXPORT_SYMBOL(acpi_get_local_address); + +#define ACPI_MAX_SUB_BUF_SIZE 9 + +const char *acpi_get_subsystem_id(acpi_handle handle) { - acpi_status status = AE_OK; - union acpi_object *package = NULL; - union acpi_object *element = NULL; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - u32 i = 0; + 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); + } - if (!list) { - return AE_BAD_PARAMETER; + 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); + +bool acpi_evaluate_reference(acpi_handle handle, acpi_string pathname, + struct acpi_object_list *arguments, + struct acpi_handle_list *list) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *package; + acpi_status status; + bool ret = false; + u32 i; + + if (!list) + return false; + /* Evaluate object. */ status = acpi_evaluate_object(handle, pathname, arguments, &buffer); @@ -338,65 +360,141 @@ acpi_evaluate_reference(acpi_handle handle, package = buffer.pointer; - if ((buffer.length == 0) || !package) { - status = AE_BAD_DATA; - acpi_util_eval_error(handle, pathname, status); - goto end; - } - if (package->type != ACPI_TYPE_PACKAGE) { - status = AE_BAD_DATA; - acpi_util_eval_error(handle, pathname, status); - goto end; - } - if (!package->package.count) { - status = AE_BAD_DATA; - acpi_util_eval_error(handle, pathname, status); - goto end; - } + if (buffer.length == 0 || !package || + package->type != ACPI_TYPE_PACKAGE || !package->package.count) + goto err; - if (package->package.count > ACPI_MAX_HANDLES) { - return AE_NO_MEMORY; - } list->count = package->package.count; + list->handles = kcalloc(list->count, sizeof(*list->handles), GFP_KERNEL); + if (!list->handles) + goto err_clear; /* Extract package data. */ for (i = 0; i < list->count; i++) { + union acpi_object *element = &(package->package.elements[i]); - element = &(package->package.elements[i]); - - if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { - status = AE_BAD_DATA; - acpi_util_eval_error(handle, pathname, status); - break; - } + if (element->type != ACPI_TYPE_LOCAL_REFERENCE || + !element->reference.handle) + goto err_free; - if (!element->reference.handle) { - status = AE_NULL_ENTRY; - acpi_util_eval_error(handle, pathname, status); - break; - } /* Get the acpi_handle. */ list->handles[i] = element->reference.handle; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", - list->handles[i])); + acpi_handle_debug(list->handles[i], "Found in reference list\n"); } - end: - if (ACPI_FAILURE(status)) { - list->count = 0; - //kfree(list->handles); - } + ret = true; +end: kfree(buffer.pointer); - return status; + return ret; + +err_free: + kfree(list->handles); + list->handles = NULL; + +err_clear: + list->count = 0; + +err: + acpi_util_eval_error(handle, pathname, status); + goto end; } EXPORT_SYMBOL(acpi_evaluate_reference); -acpi_status +/** + * acpi_handle_list_equal - Check if two ACPI handle lists are the same + * @list1: First list to compare. + * @list2: Second list to compare. + * + * Return true if the given ACPI handle lists are of the same size and + * contain the same ACPI handles in the same order. Otherwise, return false. + */ +bool acpi_handle_list_equal(struct acpi_handle_list *list1, + struct acpi_handle_list *list2) +{ + return list1->count == list2->count && + !memcmp(list1->handles, list2->handles, + list1->count * sizeof(*list1->handles)); +} +EXPORT_SYMBOL_GPL(acpi_handle_list_equal); + +/** + * acpi_handle_list_replace - Replace one ACPI handle list with another + * @dst: ACPI handle list to replace. + * @src: Source ACPI handle list. + * + * Free the handles table in @dst, move the handles table from @src to @dst, + * copy count from @src to @dst and clear @src. + */ +void acpi_handle_list_replace(struct acpi_handle_list *dst, + struct acpi_handle_list *src) +{ + if (dst->count) + kfree(dst->handles); + + dst->count = src->count; + dst->handles = src->handles; + + src->handles = NULL; + src->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_replace); + +/** + * acpi_handle_list_free - Free the handles table in an ACPI handle list + * @list: ACPI handle list to free. + * + * Free the handles table in @list and clear its count field. + */ +void acpi_handle_list_free(struct acpi_handle_list *list) +{ + if (!list->count) + return; + + kfree(list->handles); + list->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_free); + +/** + * acpi_device_dep - Check ACPI device dependency + * @target: ACPI handle of the target ACPI device. + * @match: ACPI handle to look up in the target's _DEP list. + * + * Return true if @match is present in the list returned by _DEP for + * @target or false otherwise. + */ +bool acpi_device_dep(acpi_handle target, acpi_handle match) +{ + struct acpi_handle_list dep_devices; + bool ret = false; + int i; + + if (!acpi_has_method(target, "_DEP")) + return false; + + if (!acpi_evaluate_reference(target, "_DEP", NULL, &dep_devices)) { + acpi_handle_debug(target, "Failed to evaluate _DEP.\n"); + return false; + } + + for (i = 0; i < dep_devices.count; i++) { + if (dep_devices.handles[i] == match) { + ret = true; + break; + } + } + + acpi_handle_list_free(&dep_devices); + return ret; +} +EXPORT_SYMBOL_GPL(acpi_device_dep); + +bool acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) { acpi_status status; @@ -404,9 +502,8 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld union acpi_object *output; status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer); - if (ACPI_FAILURE(status)) - return status; + return false; output = buffer.pointer; @@ -425,7 +522,7 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld out: kfree(buffer.pointer); - return status; + return ACPI_SUCCESS(status); } EXPORT_SYMBOL(acpi_get_physical_device_location); @@ -467,10 +564,11 @@ EXPORT_SYMBOL(acpi_evaluate_ost); /** * acpi_handle_path: Return the object path of handle + * @handle: ACPI device handle * * Caller must free the returned buffer */ -static char *acpi_handle_path(acpi_handle handle) +char *acpi_handle_path(acpi_handle handle) { struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, @@ -485,6 +583,9 @@ static char *acpi_handle_path(acpi_handle handle) /** * acpi_handle_printk: Print message with ACPI prefix and object path + * @level: log level + * @handle: ACPI device handle + * @fmt: format string * * This function is called through acpi_handle_<level> macros and prints * a message with ACPI prefix and object path. This function acquires @@ -503,7 +604,7 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) vaf.va = &args; path = acpi_handle_path(handle); - printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf); + printk("%sACPI: %s: %pV", level, path ? path : "<n/a>", &vaf); va_end(args); kfree(path); @@ -513,6 +614,9 @@ EXPORT_SYMBOL(acpi_handle_printk); #if defined(CONFIG_DYNAMIC_DEBUG) /** * __acpi_handle_debug: pr_debug with ACPI prefix and object path + * @descriptor: Dynamic Debug descriptor + * @handle: ACPI device handle + * @fmt: format string * * This function is called through acpi_handle_debug macro and debug * prints a message with ACPI prefix and object path. This function @@ -541,6 +645,20 @@ EXPORT_SYMBOL(__acpi_handle_debug); #endif /** + * acpi_evaluation_failure_warn - Log evaluation failure warning. + * @handle: Parent object handle. + * @name: Name of the object whose evaluation has failed. + * @status: Status value returned by the failing object evaluation. + */ +void acpi_evaluation_failure_warn(acpi_handle handle, const char *name, + acpi_status status) +{ + acpi_handle_warn(handle, "%s evaluation failed: %s\n", name, + acpi_format_exception(status)); +} +EXPORT_SYMBOL_GPL(acpi_evaluation_failure_warn); + +/** * acpi_has_method: Check whether @handle has a method named @name * @handle: ACPI device handle * @name: name of object or method @@ -611,6 +729,31 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) } /** + * acpi_evaluate_reg: Evaluate _REG method to register OpRegion presence + * @handle: ACPI device handle + * @space_id: ACPI address space id to register OpRegion presence for + * @function: Parameter to pass to _REG one of ACPI_REG_CONNECT or + * ACPI_REG_DISCONNECT + * + * Evaluate device's _REG method to register OpRegion presence. + */ +acpi_status acpi_evaluate_reg(acpi_handle handle, u8 space_id, u32 function) +{ + struct acpi_object_list arg_list; + union acpi_object params[2]; + + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = space_id; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = function; + arg_list.count = 2; + arg_list.pointer = params; + + return acpi_evaluate_object(handle, "_REG", &arg_list, NULL); +} +EXPORT_SYMBOL(acpi_evaluate_reg); + +/** * acpi_evaluate_dsm - evaluate device's _DSM method * @handle: ACPI device handle * @guid: GUID of requested functions, should be 16 bytes @@ -657,7 +800,8 @@ acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func, if (ret != AE_NOT_FOUND) acpi_handle_warn(handle, - "failed to evaluate _DSM (0x%x)\n", ret); + "failed to evaluate _DSM %pUb rev:%lld func:%lld (0x%x)\n", + guid, rev, func, ret); return NULL; } @@ -707,6 +851,30 @@ bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs) EXPORT_SYMBOL(acpi_check_dsm); /** + * acpi_dev_uid_to_integer - treat ACPI device _UID as integer + * @adev: ACPI device to get _UID from + * @integer: output buffer for integer + * + * Considers _UID as integer and converts it to @integer. + * + * Returns 0 on success, or negative error code otherwise. + */ +int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer) +{ + const char *uid; + + if (!adev) + return -ENODEV; + + uid = acpi_device_uid(adev); + if (!uid) + return -ENODATA; + + return kstrtou64(uid, 0, integer); +} +EXPORT_SYMBOL(acpi_dev_uid_to_integer); + +/** * acpi_dev_found - Detect presence of a given ACPI device in the namespace. * @hid: Hardware ID of the device. * @@ -736,24 +904,23 @@ bool acpi_dev_found(const char *hid) } EXPORT_SYMBOL(acpi_dev_found); -struct acpi_dev_present_info { +struct acpi_dev_match_info { struct acpi_device_id hid[2]; const char *uid; s64 hrv; }; -static int acpi_dev_present_cb(struct device *dev, void *data) +static int acpi_dev_match_cb(struct device *dev, const void *data) { struct acpi_device *adev = to_acpi_device(dev); - struct acpi_dev_present_info *match = data; + const struct acpi_dev_match_info *match = data; unsigned long long hrv; acpi_status status; if (acpi_match_device_ids(adev, match->hid)) return 0; - if (match->uid && (!adev->pnp.unique_id || - strcmp(adev->pnp.unique_id, match->uid))) + if (match->uid && !acpi_dev_uid_match(adev, match->uid)) return 0; if (match->hrv == -1) @@ -776,7 +943,7 @@ static int acpi_dev_present_cb(struct device *dev, void *data) * Note that if the device is pluggable, it may since have disappeared. * * Note that unlike acpi_dev_found() this function checks the status - * of the device. So for devices which are present in the dsdt, but + * of the device. So for devices which are present in the DSDT, but * which are disabled (their _STA callback returns 0) this function * will return false. * @@ -788,20 +955,83 @@ static int acpi_dev_present_cb(struct device *dev, void *data) */ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv) { - struct acpi_dev_present_info match = {}; + struct acpi_dev_match_info match = {}; struct device *dev; - strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id)); + strscpy(match.hid[0].id, hid, sizeof(match.hid[0].id)); match.uid = uid; match.hrv = hrv; - dev = bus_find_device(&acpi_bus_type, NULL, &match, - acpi_dev_present_cb); - + dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb); + put_device(dev); return !!dev; } EXPORT_SYMBOL(acpi_dev_present); +/** + * acpi_dev_get_next_match_dev - Return the next match of ACPI device + * @adev: Pointer to the previous ACPI device matching this @hid, @uid and @hrv + * @hid: Hardware ID of the device. + * @uid: Unique ID of the device, pass NULL to not check _UID + * @hrv: Hardware Revision of the device, pass -1 to not check _HRV + * + * Return the next match of ACPI device if another matching device was present + * at the moment of invocation, or NULL otherwise. + * + * The caller is responsible for invoking acpi_dev_put() on the returned device. + * On the other hand the function invokes acpi_dev_put() on the given @adev + * assuming that its reference counter had been increased beforehand. + * + * See additional information in acpi_dev_present() as well. + */ +struct acpi_device * +acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv) +{ + struct device *start = adev ? &adev->dev : NULL; + struct acpi_dev_match_info match = {}; + struct device *dev; + + strscpy(match.hid[0].id, hid, sizeof(match.hid[0].id)); + match.uid = uid; + match.hrv = hrv; + + dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb); + acpi_dev_put(adev); + return dev ? to_acpi_device(dev) : NULL; +} +EXPORT_SYMBOL(acpi_dev_get_next_match_dev); + +/** + * acpi_dev_get_first_match_dev - Return the first match of ACPI device + * @hid: Hardware ID of the device. + * @uid: Unique ID of the device, pass NULL to not check _UID + * @hrv: Hardware Revision of the device, pass -1 to not check _HRV + * + * Return the first match of ACPI device if a matching device was present + * at the moment of invocation, or NULL otherwise. + * + * The caller is responsible for invoking acpi_dev_put() on the returned device. + * + * See additional information in acpi_dev_present() as well. + */ +struct acpi_device * +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv) +{ + return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv); +} +EXPORT_SYMBOL(acpi_dev_get_first_match_dev); + +/** + * acpi_reduced_hardware - Return if this is an ACPI-reduced-hw machine + * + * Return true when running on an ACPI-reduced-hw machine, false otherwise. + */ +bool acpi_reduced_hardware(void) +{ + return acpi_gbl_reduced_hardware; +} +EXPORT_SYMBOL_GPL(acpi_reduced_hardware); + /* * acpi_backlight= handling, this is done here rather then in video_detect.c * because __setup cannot be used in modules. @@ -811,8 +1041,44 @@ EXPORT_SYMBOL(acpi_video_backlight_string); static int __init acpi_backlight(char *str) { - strlcpy(acpi_video_backlight_string, str, + strscpy(acpi_video_backlight_string, str, sizeof(acpi_video_backlight_string)); return 1; } __setup("acpi_backlight=", acpi_backlight); + +/** + * acpi_match_platform_list - Check if the system matches with a given list + * @plat: pointer to acpi_platform_list table terminated by a NULL entry + * + * Return the matched index if the system is found in the platform list. + * Otherwise, return a negative error code. + */ +int acpi_match_platform_list(const struct acpi_platform_list *plat) +{ + struct acpi_table_header hdr; + int idx = 0; + + if (acpi_disabled) + return -ENODEV; + + for (; plat->oem_id[0]; plat++, idx++) { + if (ACPI_FAILURE(acpi_get_table_header(plat->table, 0, &hdr))) + continue; + + if (strncmp(plat->oem_id, hdr.oem_id, ACPI_OEM_ID_SIZE)) + continue; + + if (strncmp(plat->oem_table_id, hdr.oem_table_id, ACPI_OEM_TABLE_ID_SIZE)) + continue; + + if ((plat->pred == all_versions) || + (plat->pred == less_than_or_equal && hdr.oem_revision <= plat->oem_revision) || + (plat->pred == greater_than_or_equal && hdr.oem_revision >= plat->oem_revision) || + (plat->pred == equal && hdr.oem_revision == plat->oem_revision)) + return idx; + } + + return -ENODEV; +} +EXPORT_SYMBOL(acpi_match_platform_list); |
