diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acdebug.h | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 15 | ||||
-rw-r--r-- | drivers/acpi/acpica/acparser.h | 3 | ||||
-rw-r--r-- | drivers/acpi/acpica/acpredef.h | 45 | ||||
-rw-r--r-- | drivers/acpi/acpica/acutils.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsmethod.c | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwpci.c | 9 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsprepkg.c | 13 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/psopinfo.c | 3 | ||||
-rw-r--r-- | drivers/acpi/acpica/utfileio.c | 9 | ||||
-rw-r--r-- | drivers/acpi/acpica/utglobal.c | 13 | ||||
-rw-r--r-- | drivers/acpi/acpica/uthex.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/utxferror.c | 11 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 56 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 12 | ||||
-rw-r--r-- | drivers/acpi/property.c | 54 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 162 | ||||
-rw-r--r-- | drivers/acpi/sbshc.c | 22 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 30 |
22 files changed, 379 insertions, 99 deletions
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index b193f8425999..ff6d8adc9cda 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -304,6 +304,8 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"PNPb006"}, /* cs423x-pnpbios */ {"CSC0100"}, + {"CSC0103"}, + {"CSC0110"}, {"CSC0000"}, {"GIM0100"}, /* Guillemot Turtlebeach something appears to be cs4232 compatible */ /* es18xx-pnpbios */ diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 4169bb87a996..43685dd36c77 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -231,7 +231,9 @@ void acpi_db_open_debug_file(char *name); acpi_status acpi_db_load_acpi_table(char *filename); acpi_status -acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table); +acpi_db_get_table_from_file(char *filename, + struct acpi_table_header **table, + u8 must_be_aml_table); /* * dbhistry - debugger HISTORY command diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 87b27521fcac..ffdb956391f6 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -352,11 +352,21 @@ struct acpi_package_info3 { u16 reserved; }; +struct acpi_package_info4 { + u8 type; + u8 object_type1; + u8 count1; + u8 sub_object_types; + u8 pkg_count; + u16 reserved; +}; + union acpi_predefined_info { struct acpi_name_info info; struct acpi_package_info ret_info; struct acpi_package_info2 ret_info2; struct acpi_package_info3 ret_info3; + struct acpi_package_info4 ret_info4; }; /* Reset to default packing */ @@ -1165,4 +1175,9 @@ struct ah_uuid { char *string; }; +struct ah_table { + char *signature; + char *description; +}; + #endif /* __ACLOCAL_H__ */ diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index 74a390c6db16..0cdd2fce493a 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -70,6 +70,9 @@ * *****************************************************************************/ +extern const u8 acpi_gbl_short_op_index[]; +extern const u8 acpi_gbl_long_op_index[]; + /* * psxface - Parser external interfaces */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index a972d11c97c9..b9474b529fcb 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -105,6 +105,11 @@ * count = 0 (optional) * (Used for _DLM) * + * ACPI_PTYPE2_VAR_VAR: Variable number of subpackages, each of either a + * constant or variable length. The subpackages are preceded by a + * constant number of objects. + * (Used for _LPI, _RDI) + * * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID * defines the format of the package. Zero-length parent package is * allowed. @@ -123,7 +128,8 @@ enum acpi_return_package_types { ACPI_PTYPE2_MIN = 8, ACPI_PTYPE2_REV_FIXED = 9, ACPI_PTYPE2_FIX_VAR = 10, - ACPI_PTYPE2_UUID_PAIR = 11 + ACPI_PTYPE2_VAR_VAR = 11, + ACPI_PTYPE2_UUID_PAIR = 12 }; /* Support macros for users of the predefined info table */ @@ -172,7 +178,7 @@ enum acpi_return_package_types { * These are the names that can actually be evaluated via acpi_evaluate_object. * Not present in this table are the following: * - * 1) Predefined/Reserved names that are never evaluated via + * 1) Predefined/Reserved names that are not usually evaluated via * acpi_evaluate_object: * _Lxx and _Exx GPE methods * _Qxx EC methods @@ -361,6 +367,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + {{"_BTH", METHOD_1ARGS(ACPI_TYPE_INTEGER), /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + {{"_BTM", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -390,6 +399,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, 0, 0, 0), + {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_CRS", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -445,7 +457,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, - {{"_DSD", METHOD_0ARGS, + {{"_DSD", METHOD_0ARGS, /* ACPI 6.0 */ METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_PACKAGE, 1, 0), @@ -604,6 +616,12 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Int) */ PACKAGE_INFO(ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0), + {{"_LPI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (3 Int, n Pkg (10 Int/Buf) */ + PACKAGE_INFO(ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 3, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | ACPI_RTYPE_STRING, + 10, 0), + {{"_MAT", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -624,6 +642,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_MTL", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_NTT", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -716,6 +737,10 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + {{"_PRR", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Ref) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_REFERENCE, 1, 0, 0, 0), + {{"_PRS", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -796,6 +821,11 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_PXM", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_RDI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int, n Pkg (m Ref)) */ + PACKAGE_INFO(ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 1, + ACPI_RTYPE_REFERENCE, 0, 0), + {{"_REG", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, @@ -808,6 +838,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_ROM", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + {{"_RST", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + {{"_RTV", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -935,6 +968,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_TDL", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_TFP", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_TIP", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -959,6 +995,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int with count */ PACKAGE_INFO(ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + {{"_TSN", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_REFERENCE)}}, + {{"_TSP", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 2b3c5bd222f1..d49f5c7a20d9 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -251,7 +251,7 @@ extern const u8 _acpi_ctype[]; #define _ACPI_DI 0x04 /* '0'-'9' */ #define _ACPI_LO 0x02 /* 'a'-'z' */ #define _ACPI_PU 0x10 /* punctuation */ -#define _ACPI_SP 0x08 /* space */ +#define _ACPI_SP 0x08 /* space, tab, CR, LF, VT, FF */ #define _ACPI_UP 0x01 /* 'A'-'Z' */ #define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index d72565a3c646..85bb951430d9 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -116,6 +116,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, walk_state = acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL); if (!walk_state) { + acpi_ps_free_op(op); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -125,6 +126,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, obj_desc->method.aml_length, NULL, 0); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); + acpi_ps_free_op(op); return_ACPI_STATUS(status); } @@ -133,9 +135,6 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, /* Parse the method, scan for creation of named objects */ status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index c5214dec4988..f785ea788356 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -123,7 +123,7 @@ acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, acpi_handle root_pci_device, acpi_handle pci_region) { acpi_status status; - struct acpi_pci_device *list_head = NULL; + struct acpi_pci_device *list_head; ACPI_FUNCTION_TRACE(hw_derive_pci_id); @@ -177,13 +177,13 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, acpi_handle parent_device; acpi_status status; struct acpi_pci_device *list_element; - struct acpi_pci_device *list_head = NULL; /* * Ascend namespace branch until the root_pci_device is reached, building * a list of device nodes. Loop will exit when either the PCI device is * found, or the root of the namespace is reached. */ + *return_list_head = NULL; current_device = pci_region; while (1) { status = acpi_get_parent(current_device, &parent_device); @@ -198,7 +198,6 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ if (parent_device == root_pci_device) { - *return_list_head = list_head; return (AE_OK); } @@ -213,9 +212,9 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, /* Put new element at the head of the list */ - list_element->next = list_head; + list_element->next = *return_list_head; list_element->device = parent_device; - list_head = list_element; + *return_list_head = list_element; current_device = parent_device; } diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 8b79958b7aca..9bb251932b45 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -316,6 +316,13 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, acpi_ns_check_package_list(info, package, elements, count); break; + case ACPI_PTYPE2_VAR_VAR: + /* + * Returns a variable list of packages, each with a variable list + * of objects. + */ + break; + case ACPI_PTYPE2_UUID_PAIR: /* The package must contain pairs of (UUID + type) */ @@ -487,6 +494,12 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, } break; + case ACPI_PTYPE2_VAR_VAR: + /* + * Each subpackage has a fixed or variable number of elements + */ + break; + case ACPI_PTYPE2_FIXED: /* Each subpackage has a fixed length */ diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 151fcd95ba84..77d8103d0094 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -497,10 +497,10 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_REV_FIXED: case ACPI_PTYPE2_FIX_VAR: - break; default: + case ACPI_PTYPE2_VAR_VAR: case ACPI_PTYPE1_FIXED: case ACPI_PTYPE1_OPTION: return; diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c index 20e1a35169fc..58310907fa7b 100644 --- a/drivers/acpi/acpica/psopinfo.c +++ b/drivers/acpi/acpica/psopinfo.c @@ -50,9 +50,6 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopinfo") -extern const u8 acpi_gbl_short_op_index[]; -extern const u8 acpi_gbl_long_op_index[]; - static const u8 acpi_gbl_argument_count[] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c index 7e1168be39fa..857af824337b 100644 --- a/drivers/acpi/acpica/utfileio.c +++ b/drivers/acpi/acpica/utfileio.c @@ -198,11 +198,8 @@ acpi_ut_read_table(FILE * fp, table_header.length, file_size); #ifdef ACPI_ASL_COMPILER - status = fl_check_for_ascii(fp, NULL, FALSE); - if (ACPI_SUCCESS(status)) { - acpi_os_printf - ("File appears to be ASCII only, must be binary\n"); - } + acpi_os_printf("File is corrupt or is ASCII text -- " + "it must be a binary file\n"); #endif return (AE_BAD_HEADER); } @@ -315,7 +312,7 @@ acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) /* Get the entire file */ fprintf(stderr, - "Loading Acpi table from file %10s - Length %.8u (%06X)\n", + "Reading ACPI table from file %10s - Length %.8u (0x%06X)\n", filename, file_size, file_size); status = acpi_ut_read_table(file, table, &table_length); diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index a72685c1e819..5e8df9177da4 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -102,19 +102,12 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { {"_SB_", ACPI_TYPE_DEVICE, NULL}, {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, {"_TZ_", ACPI_TYPE_DEVICE, NULL}, - /* - * March, 2015: - * The _REV object is in the process of being deprecated, because - * other ACPI implementations permanently return 2. Thus, it - * has little or no value. Return 2 for compatibility with - * other ACPI implementations. - */ - {"_REV", ACPI_TYPE_INTEGER, ACPI_CAST_PTR(char, 2)}, + {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, - {"_GL_", ACPI_TYPE_MUTEX, ACPI_CAST_PTR(char, 1)}, + {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) - {"_OSI", ACPI_TYPE_METHOD, ACPI_CAST_PTR(char, 1)}, + {"_OSI", ACPI_TYPE_METHOD, (char *)1}, #endif /* Table terminator */ diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c index aa448278ba28..fda8b3def81c 100644 --- a/drivers/acpi/acpica/uthex.c +++ b/drivers/acpi/acpica/uthex.c @@ -75,9 +75,9 @@ char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) /******************************************************************************* * - * FUNCTION: acpi_ut_hex_char_to_value + * FUNCTION: acpi_ut_ascii_char_to_hex * - * PARAMETERS: ascii_char - Hex character in Ascii + * PARAMETERS: hex_char - Hex character in Ascii * * RETURN: The binary value of the ascii/hex character * diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 306e785f9418..98d578753101 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -107,9 +107,16 @@ acpi_exception(const char *module_name, va_list arg_list; ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", - acpi_format_exception(status)); + /* For AE_OK, just print the message */ + + if (ACPI_SUCCESS(status)) { + acpi_os_printf(ACPI_MSG_EXCEPTION); + + } else { + acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", + acpi_format_exception(status)); + } va_start(arg_list, format); acpi_os_vprintf(format, arg_list); ACPI_MSG_SUFFIX; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c412fdb28d34..513e7230e3d0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -470,6 +470,16 @@ static int __init acpi_bus_init_irq(void) return 0; } +/** + * acpi_early_init - Initialize ACPICA and populate the ACPI namespace. + * + * The ACPI tables are accessible after this, but the handling of events has not + * been initialized and the global lock is not available yet, so AML should not + * be executed at this point. + * + * Doing this before switching the EFI runtime services to virtual mode allows + * the EfiBootServices memory to be freed slightly earlier on boot. + */ void __init acpi_early_init(void) { acpi_status status; @@ -533,26 +543,42 @@ void __init acpi_early_init(void) acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; } #endif + return; + + error0: + disable_acpi(); +} + +/** + * acpi_subsystem_init - Finalize the early initialization of ACPI. + * + * Switch over the platform to the ACPI mode (if possible), initialize the + * handling of ACPI events, install the interrupt and global lock handlers. + * + * Doing this too early is generally unsafe, but at the same time it needs to be + * done before all things that really depend on ACPI. The right spot appears to + * be before finalizing the EFI initialization. + */ +void __init acpi_subsystem_init(void) +{ + acpi_status status; + + if (acpi_disabled) + return; status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); - goto error0; + disable_acpi(); + } else { + /* + * If the system is using ACPI then we can be reasonably + * confident that any regulators are managed by the firmware + * so tell the regulator core it has everything it needs to + * know. + */ + regulator_has_full_constraints(); } - - /* - * If the system is using ACPI then we can be reasonably - * confident that any regulators are managed by the firmware - * so tell the regulator core it has everything it needs to - * know. - */ - regulator_has_full_constraints(); - - return; - - error0: - disable_acpi(); - return; } static int __init acpi_bus_init(void) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ba4a61e964be..d93628c65661 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -191,6 +191,8 @@ bool acpi_osi_is_win8(void); /*-------------------------------------------------------------------------- Device properties -------------------------------------------------------------------------- */ +#define ACPI_DT_NAMESPACE_HID "PRP0001" + void acpi_init_properties(struct acpi_device *adev); void acpi_free_properties(struct acpi_device *adev); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 39748bb3a543..5226a8b921ae 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -175,14 +175,10 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, if (!addr || !length) return; - /* Resources are never freed */ - if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) - request_region(addr, length, desc); - else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - request_mem_region(addr, length, desc); + acpi_reserve_region(addr, length, gas->space_id, 0, desc); } -static int __init acpi_reserve_resources(void) +static void __init acpi_reserve_resources(void) { acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, "ACPI PM1a_EVT_BLK"); @@ -211,10 +207,7 @@ static int __init acpi_reserve_resources(void) if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) acpi_request_region(&acpi_gbl_FADT.xgpe1_block, acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); - - return 0; } -device_initcall(acpi_reserve_resources); void acpi_os_printf(const char *fmt, ...) { @@ -1845,6 +1838,7 @@ acpi_status __init acpi_os_initialize(void) acpi_status __init acpi_os_initialize1(void) { + acpi_reserve_resources(); kacpid_wq = alloc_workqueue("kacpid", 0, 1); kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 0d083736e25b..7836e2e980f4 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -79,50 +79,51 @@ static bool acpi_properties_format_valid(const union acpi_object *properties) static void acpi_init_of_compatible(struct acpi_device *adev) { const union acpi_object *of_compatible; - struct acpi_hardware_id *hwid; - bool acpi_of = false; int ret; - /* - * Check if the special PRP0001 ACPI ID is present and in that - * case we fill in Device Tree compatible properties for this - * device. - */ - list_for_each_entry(hwid, &adev->pnp.ids, list) { - if (!strcmp(hwid->id, "PRP0001")) { - acpi_of = true; - break; - } - } - - if (!acpi_of) - return; - ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, &of_compatible); if (ret) { ret = acpi_dev_get_property(adev, "compatible", ACPI_TYPE_STRING, &of_compatible); if (ret) { - acpi_handle_warn(adev->handle, - "PRP0001 requires compatible property\n"); + if (adev->parent + && adev->parent->flags.of_compatible_ok) + goto out; + return; } } adev->data.of_compatible = of_compatible; + + out: + adev->flags.of_compatible_ok = 1; } void acpi_init_properties(struct acpi_device *adev) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + bool acpi_of = false; + struct acpi_hardware_id *hwid; const union acpi_object *desc; acpi_status status; int i; + /* + * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in + * Device Tree compatible properties for this device. + */ + list_for_each_entry(hwid, &adev->pnp.ids, list) { + if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) { + acpi_of = true; + break; + } + } + status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, ACPI_TYPE_PACKAGE); if (ACPI_FAILURE(status)) - return; + goto out; desc = buf.pointer; if (desc->package.count % 2) @@ -156,13 +157,20 @@ void acpi_init_properties(struct acpi_device *adev) adev->data.pointer = buf.pointer; adev->data.properties = properties; - acpi_init_of_compatible(adev); - return; + if (acpi_of) + acpi_init_of_compatible(adev); + + goto out; } fail: - dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n"); + dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n"); ACPI_FREE(buf.pointer); + + out: + if (acpi_of && !adev->flags.of_compatible_ok) + acpi_handle_info(adev->handle, + ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); } void acpi_free_properties(struct acpi_device *adev) diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 5589a6e2a023..fcb7807ea8b7 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -26,6 +26,7 @@ #include <linux/device.h> #include <linux/export.h> #include <linux/ioport.h> +#include <linux/list.h> #include <linux/slab.h> #ifdef CONFIG_X86 @@ -573,7 +574,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_resources); * @ares: Input ACPI resource object. * @types: Valid resource types of IORESOURCE_XXX * - * This is a hepler function to support acpi_dev_get_resources(), which filters + * This is a helper function to support acpi_dev_get_resources(), which filters * ACPI resource objects according to resource types. */ int acpi_dev_filter_resource_type(struct acpi_resource *ares, @@ -621,3 +622,162 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares, return (type & types) ? 0 : 1; } EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); + +struct reserved_region { + struct list_head node; + u64 start; + u64 end; +}; + +static LIST_HEAD(reserved_io_regions); +static LIST_HEAD(reserved_mem_regions); + +static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, + char *desc) +{ + unsigned int length = end - start + 1; + struct resource *res; + + res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? + request_region(start, length, desc) : + request_mem_region(start, length, desc); + if (!res) + return -EIO; + + res->flags &= ~flags; + return 0; +} + +static int add_region_before(u64 start, u64 end, u8 space_id, + unsigned long flags, char *desc, + struct list_head *head) +{ + struct reserved_region *reg; + int error; + + reg = kmalloc(sizeof(*reg), GFP_KERNEL); + if (!reg) + return -ENOMEM; + + error = request_range(start, end, space_id, flags, desc); + if (error) + return error; + + reg->start = start; + reg->end = end; + list_add_tail(®->node, head); + return 0; +} + +/** + * acpi_reserve_region - Reserve an I/O or memory region as a system resource. + * @start: Starting address of the region. + * @length: Length of the region. + * @space_id: Identifier of address space to reserve the region from. + * @flags: Resource flags to clear for the region after requesting it. + * @desc: Region description (for messages). + * + * Reserve an I/O or memory region as a system resource to prevent others from + * using it. If the new region overlaps with one of the regions (in the given + * address space) already reserved by this routine, only the non-overlapping + * parts of it will be reserved. + * + * Returned is either 0 (success) or a negative error code indicating a resource + * reservation problem. It is the code of the first encountered error, but the + * routine doesn't abort until it has attempted to request all of the parts of + * the new region that don't overlap with other regions reserved previously. + * + * The resources requested by this routine are never released. + */ +int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, + unsigned long flags, char *desc) +{ + struct list_head *regions; + struct reserved_region *reg; + u64 end = start + length - 1; + int ret = 0, error = 0; + + if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) + regions = &reserved_io_regions; + else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + regions = &reserved_mem_regions; + else + return -EINVAL; + + if (list_empty(regions)) + return add_region_before(start, end, space_id, flags, desc, regions); + + list_for_each_entry(reg, regions, node) + if (reg->start == end + 1) { + /* The new region can be prepended to this one. */ + ret = request_range(start, end, space_id, flags, desc); + if (!ret) + reg->start = start; + + return ret; + } else if (reg->start > end) { + /* No overlap. Add the new region here and get out. */ + return add_region_before(start, end, space_id, flags, + desc, ®->node); + } else if (reg->end == start - 1) { + goto combine; + } else if (reg->end >= start) { + goto overlap; + } + + /* The new region goes after the last existing one. */ + return add_region_before(start, end, space_id, flags, desc, regions); + + overlap: + /* + * The new region overlaps an existing one. + * + * The head part of the new region immediately preceding the existing + * overlapping one can be combined with it right away. + */ + if (reg->start > start) { + error = request_range(start, reg->start - 1, space_id, flags, desc); + if (error) + ret = error; + else + reg->start = start; + } + + combine: + /* + * The new region is adjacent to an existing one. If it extends beyond + * that region all the way to the next one, it is possible to combine + * all three of them. + */ + while (reg->end < end) { + struct reserved_region *next = NULL; + u64 a = reg->end + 1, b = end; + + if (!list_is_last(®->node, regions)) { + next = list_next_entry(reg, node); + if (next->start <= end) + b = next->start - 1; + } + error = request_range(a, b, space_id, flags, desc); + if (!error) { + if (next && next->start == b + 1) { + reg->end = next->end; + list_del(&next->node); + kfree(next); + } else { + reg->end = end; + break; + } + } else if (next) { + if (!ret) + ret = error; + + reg = next; + } else { + break; + } + } + + return ret ? ret : error; +} +EXPORT_SYMBOL_GPL(acpi_reserve_region); diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 26e5b5060523..bf034f8b7c1a 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -14,6 +14,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/dmi.h> #include "sbshc.h" #define PREFIX "ACPI: " @@ -87,6 +88,8 @@ enum acpi_smb_offset { ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */ }; +static bool macbook; + static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data) { return ec_read(hc->offset + address, data); @@ -132,6 +135,8 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, } mutex_lock(&hc->lock); + if (macbook) + udelay(5); if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp)) goto end; if (temp) { @@ -257,12 +262,29 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, void *data); +static int macbook_dmi_match(const struct dmi_system_id *d) +{ + pr_debug("Detected MacBook, enabling workaround\n"); + macbook = true; + return 0; +} + +static struct dmi_system_id acpi_smbus_dmi_table[] = { + { macbook_dmi_match, "Apple MacBook", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, + }, + { }, +}; + static int acpi_smbus_hc_add(struct acpi_device *device) { int status; unsigned long long val; struct acpi_smb_hc *hc; + dmi_check_system(acpi_smbus_dmi_table); + if (!device) return -EINVAL; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 03141aa4ea95..0a099917a006 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -135,12 +135,13 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, struct acpi_hardware_id *id; /* - * Since we skip PRP0001 from the modalias below, 0 should be returned - * if PRP0001 is the only ACPI/PNP ID in the device's list. + * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should + * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the + * device's list. */ count = 0; list_for_each_entry(id, &acpi_dev->pnp.ids, list) - if (strcmp(id->id, "PRP0001")) + if (strcmp(id->id, ACPI_DT_NAMESPACE_HID)) count++; if (!count) @@ -153,7 +154,7 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, size -= len; list_for_each_entry(id, &acpi_dev->pnp.ids, list) { - if (!strcmp(id->id, "PRP0001")) + if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID)) continue; count = snprintf(&modalias[len], size, "%s:", id->id); @@ -177,7 +178,8 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, * @size: Size of the buffer. * * Expose DT compatible modalias as of:NnameTCcompatible. This function should - * only be called for devices having PRP0001 in their list of ACPI/PNP IDs. + * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of + * ACPI/PNP IDs. */ static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, int size) @@ -980,9 +982,9 @@ static void acpi_device_remove_files(struct acpi_device *dev) * @adev: ACPI device object to match. * @of_match_table: List of device IDs to match against. * - * If @dev has an ACPI companion which has the special PRP0001 device ID in its - * list of identifiers and a _DSD object with the "compatible" property, use - * that property to match against the given list of identifiers. + * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of + * identifiers and a _DSD object with the "compatible" property, use that + * property to match against the given list of identifiers. */ static bool acpi_of_match_device(struct acpi_device *adev, const struct of_device_id *of_match_table) @@ -1038,14 +1040,14 @@ static const struct acpi_device_id *__acpi_match_device( return id; /* - * Next, check the special "PRP0001" ID and try to match the + * Next, check ACPI_DT_NAMESPACE_HID and try to match the * "compatible" property if found. * * The id returned by the below is not valid, but the only * caller passing non-NULL of_ids here is only interested in * whether or not the return value is NULL. */ - if (!strcmp("PRP0001", hwid->id) + if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id) && acpi_of_match_device(device, of_ids)) return id; } @@ -1671,7 +1673,7 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, static void acpi_wakeup_gpe_init(struct acpi_device *device) { - struct acpi_device_id button_device_ids[] = { + static const struct acpi_device_id button_device_ids[] = { {"PNP0C0C", 0}, {"PNP0C0D", 0}, {"PNP0C0E", 0}, @@ -2405,7 +2407,7 @@ static void acpi_default_enumeration(struct acpi_device *device) } static const struct acpi_device_id generic_device_ids[] = { - {"PRP0001", }, + {ACPI_DT_NAMESPACE_HID, }, {"", }, }; @@ -2413,8 +2415,8 @@ static int acpi_generic_device_attach(struct acpi_device *adev, const struct acpi_device_id *not_used) { /* - * Since PRP0001 is the only ID handled here, the test below can be - * unconditional. + * Since ACPI_DT_NAMESPACE_HID is the only ID handled here, the test + * below can be unconditional. */ if (adev->data.of_compatible) acpi_default_enumeration(adev); |