From e0ae8fee0e11c1a8e9b45ab14ab5fe58d87f031d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 30 Aug 2013 14:19:29 +0200 Subject: ACPI / scan: Change ordering of locks for device hotplug Change the ordering of device hotplug locks in scan.c so that acpi_scan_lock is always acquired after device_hotplug_lock. This will make it possible to use device_hotplug_lock around some code paths that acquire acpi_scan_lock safely (most importantly system suspend and hibernation). Apart from that, acpi_scan_lock is platform-specific and device_hotplug_lock is general, so the new ordering appears to be more appropriate from the overall design viewpoint. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e2f6d9dbdf0d..42982b522b36 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -207,8 +207,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return -EINVAL; } - lock_device_hotplug(); - /* * Carry out two passes here and ignore errors in the first pass, * because if the devices in question are memory blocks and @@ -239,9 +237,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) ACPI_UINT32_MAX, acpi_bus_online_companions, NULL, NULL, NULL); - - unlock_device_hotplug(); - put_device(&device->dev); return -EBUSY; } @@ -252,8 +247,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_bus_trim(device); - unlock_device_hotplug(); - /* Device node has been unregistered. */ put_device(&device->dev); device = NULL; @@ -309,6 +302,7 @@ static void acpi_bus_device_eject(void *context) u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; + lock_device_hotplug(); mutex_lock(&acpi_scan_lock); acpi_bus_get_device(handle, &device); @@ -332,6 +326,7 @@ static void acpi_bus_device_eject(void *context) out: mutex_unlock(&acpi_scan_lock); + unlock_device_hotplug(); return; err_out: @@ -346,8 +341,8 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; - mutex_lock(&acpi_scan_lock); lock_device_hotplug(); + mutex_lock(&acpi_scan_lock); if (ost_source != ACPI_NOTIFY_BUS_CHECK) { acpi_bus_get_device(handle, &device); @@ -373,9 +368,9 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); out: - unlock_device_hotplug(); acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); mutex_unlock(&acpi_scan_lock); + unlock_device_hotplug(); } static void acpi_scan_bus_check(void *context) @@ -466,6 +461,7 @@ void acpi_bus_hot_remove_device(void *context) acpi_handle handle = device->handle; int error; + lock_device_hotplug(); mutex_lock(&acpi_scan_lock); error = acpi_scan_hot_remove(device); @@ -475,6 +471,7 @@ void acpi_bus_hot_remove_device(void *context) NULL); mutex_unlock(&acpi_scan_lock); + unlock_device_hotplug(); kfree(context); } EXPORT_SYMBOL(acpi_bus_hot_remove_device); -- cgit v1.2.3 From af65cfe9aeae03e0682bebdf4db94582d75562dd Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 2 Sep 2013 13:30:25 +0300 Subject: ACPI / LPSS: don't crash if a device has no MMIO resources Intel LPSS devices that are enumerated from ACPI have both MMIO and IRQ resources returned in their _CRS method. However, Apple Macbook Air with Haswell has LPSS devices enumerated from PCI bus instead and _CRS method returns only an interrupt number (but the device has _HID set that causes the scan handler to match it). The current ACPI / LPSS code sets pdata->dev_desc only when MMIO resource is found for the device and in case of Macbook Air it is never found. That leads to a NULL pointer dereference in register_device_clock(). Correct this by always setting the pdata->dev_desc. Reported-and-tested-by: Imre Kaloz Signed-off-by: Mika Westerberg Cc: 3.10+ # 3.10+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 6a382188fa20..fb78bb9ad8f6 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -257,12 +257,13 @@ static int acpi_lpss_create_device(struct acpi_device *adev, pdata->mmio_size = resource_size(&rentry->res); pdata->mmio_base = ioremap(rentry->res.start, pdata->mmio_size); - pdata->dev_desc = dev_desc; break; } acpi_dev_free_resource_list(&resource_list); + pdata->dev_desc = dev_desc; + if (dev_desc->clk_required) { ret = register_device_clock(adev, pdata); if (ret) { -- cgit v1.2.3 From 4be4be8fee2ee99a52f94f90d03d2f287ee1db86 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 6 Sep 2013 14:27:15 +0800 Subject: ACPICA: Fix for a Store->ArgX when ArgX contains a reference to a field. This change fixes a problem where a Store operation to an ArgX object that contained a reference to a field object did not complete the automatic dereference and then write to the actual field object. Instead, the object type of the field object was inadvertently changed to match the type of the source operand. The new behavior will actually write to the field object (buffer field or field unit), thus matching the correct ACPI-defined behavior. Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exstore.c | 166 ++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 64 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 2bdba6f7d762..f0b09bf9887d 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -57,6 +57,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, union acpi_operand_object *dest_desc, struct acpi_walk_state *walk_state); +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state); + /******************************************************************************* * * FUNCTION: acpi_ex_store @@ -375,7 +380,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * When storing into an object the data is converted to the * target object type then stored in the object. This means * that the target object type (for an initialized target) will - * not be changed by a store operation. + * not be changed by a store operation. A copy_object can change + * the target type, however. + * + * The implicit_conversion flag is set to NO/FALSE only when + * storing to an arg_x -- as per the rules of the ACPI spec. * * Assumes parameters are already validated. * @@ -399,7 +408,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); @@ -413,45 +422,30 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - /* If no implicit conversion, drop into the default case below */ - - if ((!implicit_conversion) || - ((walk_state->opcode == AML_COPY_OP) && - (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && - (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && - (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { - /* - * Force execution of default (no implicit conversion). Note: - * copy_object does not perform an implicit conversion, as per the ACPI - * spec -- except in case of region/bank/index fields -- because these - * objects must retain their original type permanently. - */ - target_type = ACPI_TYPE_ANY; - } - /* Do the actual store operation */ switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* For fields, copy the source data to the target field. */ - - status = acpi_ex_write_data_to_field(source_desc, target_desc, - &walk_state->result_obj); - break; - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object + * The simple data types all support implicit source operand + * conversion before the store. */ + + if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { + /* + * However, copy_object and Stores to arg_x do not perform + * an implicit conversion, as per the ACPI specification. + * A direct store is performed instead. + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } + + /* Store with implicit source operand conversion support */ + status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); @@ -465,13 +459,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * - * Note: This may change the type of the node if an explicit store - * has been performed such that the node/object type has been - * changed. + * Note: This may change the type of the node if an explicit + * store has been performed such that the node/object type + * has been changed. */ - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); + status = acpi_ns_attach_object(node, new_desc, + new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", @@ -482,38 +475,83 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, } break; - default: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing [%s] (%p) directly into node [%s] (%p)" - " with no implicit conversion\n", - acpi_ut_get_object_type_name(source_desc), - source_desc, - acpi_ut_get_object_type_name(target_desc), - node)); + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * For all fields, always write the source data to the target + * field. Any required implicit source operand conversion is + * performed in the function below as necessary. Note, field + * objects must retain their original type permanently. + */ + status = acpi_ex_write_data_to_field(source_desc, target_desc, + &walk_state->result_obj); + break; + default: /* * No conversions for all other types. Directly store a copy of - * the source object. NOTE: This is a departure from the ACPI - * spec, which states "If conversion is impossible, abort the - * running control method". + * the source object. This is the ACPI spec-defined behavior for + * the copy_object operator. * - * This code implements "If conversion is impossible, treat the - * Store operation as a CopyObject". + * NOTE: For the Store operator, this is a departure from the + * ACPI spec, which states "If conversion is impossible, abort + * the running control method". Instead, this code implements + * "If conversion is impossible, treat the Store operation as + * a CopyObject". */ - status = - acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); - acpi_ut_remove_reference(new_desc); + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); break; } return_ACPI_STATUS(status); } + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_direct_to_node + * + * PARAMETERS: source_desc - Value to be stored + * node - Named object to receive the value + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object directly to a node. This involves a copy + * and an attach. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *new_desc; + + ACPI_FUNCTION_TRACE(ex_store_direct_to_node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", + acpi_ut_get_object_type_name(source_desc), + source_desc, acpi_ut_get_type_name(node->type), + node)); + + /* Copy the source object to a new object */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Attach the new object to the node */ + + status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); + acpi_ut_remove_reference(new_desc); + return_ACPI_STATUS(status); +} -- cgit v1.2.3 From 11b88ee275ec8590a373396888c2460ee89364d6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 9 Sep 2013 23:07:47 +0200 Subject: ACPI / bind: Prefer device objects with _STA to those without it As reported at https://bugzilla.kernel.org/show_bug.cgi?id=60829, there still are cases in which do_find_child() doesn't choose the ACPI device object it is "expected" to choose if there are more such objects matching one PCI device present. This particular problem may be worked around by making do_find_child() return device obejcts witn _STA whose result indicates that the device is enabled before device objects without _STA if there's more than one device object to choose from. This change doesn't affect the case in which there's only one matching ACPI device object per PCI device. References: https://bugzilla.kernel.org/show_bug.cgi?id=60829 Reported-by: Peter Wu Tested-by: Felix Lisczyk Signed-off-by: Rafael J. Wysocki --- drivers/acpi/glue.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 94672297e1b1..10f0f40587bb 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -79,6 +79,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) return ret; } +#define FIND_CHILD_MIN_SCORE 1 +#define FIND_CHILD_MAX_SCORE 2 + static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, void *not_used, void **ret_p) { @@ -92,14 +95,17 @@ static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, return AE_OK; } -static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) +static int do_find_child_checks(acpi_handle handle, bool is_bridge) { + bool sta_present = true; unsigned long long sta; acpi_status status; - status = acpi_bus_get_status_handle(handle, &sta); - if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) - return false; + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + if (status == AE_NOT_FOUND) + sta_present = false; + else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) + return -ENODEV; if (is_bridge) { void *test = NULL; @@ -107,16 +113,17 @@ static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) /* Check if this object has at least one child device. */ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, acpi_dev_present, NULL, NULL, &test); - return !!test; + if (!test) + return -ENODEV; } - return true; + return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; } struct find_child_context { u64 addr; bool is_bridge; acpi_handle ret; - bool ret_checked; + int ret_score; }; static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, @@ -125,6 +132,7 @@ static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, struct find_child_context *context = data; unsigned long long addr; acpi_status status; + int score; status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); if (ACPI_FAILURE(status) || addr != context->addr) @@ -144,15 +152,20 @@ static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, * its handle if so. Second, check the same for the object that we've * just found. */ - if (!context->ret_checked) { - if (acpi_extra_checks_passed(context->ret, context->is_bridge)) + if (!context->ret_score) { + score = do_find_child_checks(context->ret, context->is_bridge); + if (score == FIND_CHILD_MAX_SCORE) return AE_CTRL_TERMINATE; else - context->ret_checked = true; + context->ret_score = score; } - if (acpi_extra_checks_passed(handle, context->is_bridge)) { + score = do_find_child_checks(handle, context->is_bridge); + if (score == FIND_CHILD_MAX_SCORE) { context->ret = handle; return AE_CTRL_TERMINATE; + } else if (score > context->ret_score) { + context->ret = handle; + context->ret_score = score; } return AE_OK; } -- cgit v1.2.3 From 6ebb5bc9e61be4315202c15a0f53f636e8f0bf2e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:09 +0800 Subject: acpi_processor: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/acpi/acpi_processor.c in this patch. Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f29e06efa479..357abdc1406a 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -219,6 +219,7 @@ static int acpi_processor_get_info(struct acpi_device *device) int cpu_index, device_declaration = 0; acpi_status status = AE_OK; static int cpu0_initialized; + unsigned long long value; if (num_online_cpus() > 1) errata.smp = TRUE; @@ -258,7 +259,6 @@ static int acpi_processor_get_info(struct acpi_device *device) * Declared with "Device" statement; match _UID. * Note that we don't handle string _UIDs yet. */ - unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { @@ -332,9 +332,9 @@ static int acpi_processor_get_info(struct acpi_device *device) * ensure we get the right value in the "physical id" field * of /proc/cpuinfo */ - status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); + status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value); if (ACPI_SUCCESS(status)) - arch_fix_phys_package_id(pr->id, object.integer.value); + arch_fix_phys_package_id(pr->id, value); return 0; } -- cgit v1.2.3 From 6a868e171c3800442f59b74ec1e0eaf7d858eb58 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:10 +0800 Subject: ACPI: dock: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/acpi/dock.c in this patch. Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 05ea4be01a83..ca86c1ce7c8a 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -441,7 +441,7 @@ static void handle_dock(struct dock_station *ds, int dock) acpi_status status; struct acpi_object_list arg_list; union acpi_object arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + unsigned long long value; acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking"); @@ -450,12 +450,10 @@ static void handle_dock(struct dock_station *ds, int dock) arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; arg.integer.value = dock; - status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); + status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n", status); - - kfree(buffer.pointer); } static inline void dock(struct dock_station *ds) -- cgit v1.2.3 From ca9f62ac783bf88c54143f8065adc0fc8df859c1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:34 +0800 Subject: ACPI / processor: Introduce apic_id in struct processor to save parsed APIC id For cpu hot add, we evaluate _MAT or parse MADT twice to get APIC id, here is the code logic: acpi_processor_add() acpi_processor_get_info() acpi_get_cpuid() will evaluate _MAT or parse MADT; acpi_processor_hotadd_init() acpi_map_lsapic() will evaluate _MAT again; This can be done more effectively, this patch introduces apic_id in struct processor to save parsed APIC id, and then we can use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 4 +++- drivers/acpi/processor_core.c | 26 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f29e06efa479..f89f914cb97e 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -270,7 +270,9 @@ static int acpi_processor_get_info(struct acpi_device *device) device_declaration = 1; pr->acpi_id = value; } - cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); + pr->apic_id = acpi_get_apicid(pr->handle, device_declaration, + pr->acpi_id); + cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index cf34d903f4fb..b3171f30b319 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -162,16 +162,23 @@ exit: return apic_id; } -int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id) { -#ifdef CONFIG_SMP - int i; -#endif - int apic_id = -1; + int apic_id; apic_id = map_mat_entry(handle, type, acpi_id); if (apic_id == -1) apic_id = map_madt_entry(type, acpi_id); + + return apic_id; +} + +int acpi_map_cpuid(int apic_id, u32 acpi_id) +{ +#ifdef CONFIG_SMP + int i; +#endif + if (apic_id == -1) { /* * On UP processor, there is no _MAT or MADT table. @@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) #endif return -1; } + +int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +{ + int apic_id; + + apic_id = acpi_get_apicid(handle, type, acpi_id); + + return acpi_map_cpuid(apic_id, acpi_id); +} EXPORT_SYMBOL_GPL(acpi_get_cpuid); static bool __init processor_physically_present(acpi_handle handle) -- cgit v1.2.3 From d536bf3dc97417471e2c5098837a1cddd7fbb3c7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:35 +0800 Subject: ACPI / processor: use apic_id and remove duplicated _MAT evaluation Since APIC id is saved in processor struct, just use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f89f914cb97e..66c9b702894b 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -181,7 +181,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr) cpu_maps_update_begin(); cpu_hotplug_begin(); - ret = acpi_map_lsapic(pr->handle, &pr->id); + ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id); if (ret) goto out; -- cgit v1.2.3 From 2d4d3e2a06bd25fba52a4693b09ec72d61d250d9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:37 +0800 Subject: ACPI / processor: remove some dead code in acpi_processor_get_info() errata.smp is used by nowhere, so the variable assignment is meanless, remove it. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 66c9b702894b..5364d029b8e9 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -220,9 +220,6 @@ static int acpi_processor_get_info(struct acpi_device *device) acpi_status status = AE_OK; static int cpu0_initialized; - if (num_online_cpus() > 1) - errata.smp = TRUE; - acpi_processor_errata(pr); /* -- cgit v1.2.3 From 082e12a05cf317acec2feaf3a78de3f3372feeb3 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Mon, 2 Sep 2013 11:57:38 +0800 Subject: ACPI / processor: remove unnecessary if (!pr) check acpi_processor_errata() is only called in acpi_processor_get_info(), and the argument 'pr' passed to acpi_processor_errata() will never be NULL, so the if (!pr) check is unnecessary and can be removed. Since the 'pr' argument is not used by acpi_processor_errata() any more, so change the argument into void too. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 5364d029b8e9..7ce075008034 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -140,15 +140,11 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) return 0; } -static int acpi_processor_errata(struct acpi_processor *pr) +static int acpi_processor_errata(void) { int result = 0; struct pci_dev *dev = NULL; - - if (!pr) - return -EINVAL; - /* * PIIX4 */ @@ -220,7 +216,7 @@ static int acpi_processor_get_info(struct acpi_device *device) acpi_status status = AE_OK; static int cpu0_initialized; - acpi_processor_errata(pr); + acpi_processor_errata(); /* * Check to see if we have bus mastering arbitration control. This -- cgit v1.2.3 From 7cc34680c1ab418d5c7fd0f9621515b7a0aa1d66 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Mon, 2 Sep 2013 11:57:39 +0800 Subject: ACPI / processor: Remove outdated comments acpi_get_processor_id() can be find nowhere, and the acpi id is synchronized to APIC id when acpi_get_cpuid() is called, so the comments can be removed. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 7ce075008034..da428929c1a4 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -240,11 +240,6 @@ static int acpi_processor_get_info(struct acpi_device *device) return -ENODEV; } - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in - * arch/xxx/acpi.c - */ pr->acpi_id = object.processor.proc_id; } else { /* -- cgit v1.2.3 From 1bb25df0fde2cdb2f250a7e7e43c2ec1ba65d0f5 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Fri, 30 Aug 2013 09:25:40 +0800 Subject: ACPI / mm: use NUMA_NO_NODE Use more appropriate NUMA_NO_NODE instead of -1 Signed-off-by: Jianguo Wu Acked-by: David Rientjes Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_memhotplug.c | 2 +- drivers/acpi/numa.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 999adb5499c7..c00a3a73409b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -281,7 +281,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) if (!info->enabled) continue; - if (nid < 0) + if (nid == NUMA_NO_NODE) nid = memory_add_physaddr_to_nid(info->start_addr); acpi_unbind_memory_blocks(info, handle); diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 2e82e5d76930..a2343a1d9e0b 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -73,7 +73,7 @@ int acpi_map_pxm_to_node(int pxm) { int node = pxm_to_node_map[pxm]; - if (node < 0) { + if (node == NUMA_NO_NODE) { if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) return NUMA_NO_NODE; node = first_unset_node(nodes_found_map); @@ -334,7 +334,7 @@ int acpi_get_pxm(acpi_handle h) int acpi_get_node(acpi_handle *handle) { - int pxm, node = -1; + int pxm, node = NUMA_NO_NODE; pxm = acpi_get_pxm(handle); if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) -- cgit v1.2.3 From bf9b59f2571d0d0470f904842a283ac7957438cd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:30:51 +0200 Subject: ACPI / processor: remove superfluous pr == NULL checks The only acpi_processor_get_power_info_fadt() user (acpi_processor_get_power_info()) dereferences pr before calling the function. The only acpi_processor_hotplug() user (acpi_cpu_soft_notify()) checks for pr == NULL before calling the function. The only acpi_processor_cst_has_changed() user (acpi_processor_notify()) checks for pr == NULL before calling the function. The only acpi_processor_power_init() user (__acpi_processor_start()) dereferences pr before calling the function. Thus remove superfluous pr == NULL checks from affected functions. Also: While at it remove redundant brackets from acpi_processor_hotplug(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_idle.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f98dd00b51a9..35c8f2bbcc40 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -272,9 +272,6 @@ static void tsc_check_state(int state) { return; } static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) { - if (!pr) - return -EINVAL; - if (!pr->pblk) return -ENODEV; @@ -1076,12 +1073,8 @@ int acpi_processor_hotplug(struct acpi_processor *pr) if (disabled_by_idle_boot_param()) return 0; - if (!pr) - return -EINVAL; - - if (nocst) { + if (nocst) return -ENODEV; - } if (!pr->flags.power_setup_done) return -ENODEV; @@ -1108,9 +1101,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) if (disabled_by_idle_boot_param()) return 0; - if (!pr) - return -EINVAL; - if (nocst) return -ENODEV; @@ -1183,9 +1173,6 @@ int acpi_processor_power_init(struct acpi_processor *pr) first_run++; } - if (!pr) - return -EINVAL; - if (acpi_gbl_FADT.cst_control && !nocst) { status = acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); -- cgit v1.2.3 From 568b6ad834e90351f1a1e6e6cf93bf0e0d8a0eae Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Fri, 30 Aug 2013 16:16:05 -0500 Subject: ACP / fan: trivial style cleanup Remove label indentation in acpi_fan_add(). Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki --- drivers/acpi/fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 41ade6570bc0..ba3da88cee45 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -168,7 +168,7 @@ static int acpi_fan_add(struct acpi_device *device) acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); - end: +end: return result; } -- cgit v1.2.3 From b938a229c85a567de7dba2d806d9f63a7c90483e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:05:54 -0600 Subject: ACPI: Rename OSC_QUERY_TYPE to OSC_QUERY_DWORD OSC_QUERY_TYPE isn't a "type"; it's an index into the _OSC Capabilities Buffer of DWORDs. Rename OSC_QUERY_TYPE, OSC_SUPPORT_TYPE, and OSC_CONTROL_TYPE to OSC_QUERY_DWORD, etc., to make this clear. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/apei/apei-base.c | 6 +++--- drivers/acpi/bus.c | 18 +++++++++--------- drivers/acpi/pci_root.c | 14 +++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 46f80e2c92f7..6d2c49b86b7f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -758,9 +758,9 @@ int apei_osc_setup(void) .cap.pointer = capbuf, }; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = 1; - capbuf[OSC_CONTROL_TYPE] = 0; + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = 1; + capbuf[OSC_CONTROL_DWORD] = 0; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)) || ACPI_FAILURE(acpi_run_osc(handle, &context))) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b587ec8257b2..fbcfaa682c15 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -255,7 +255,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) acpi_print_osc_error(handle, context, "_OSC invalid revision"); if (errors & OSC_CAPABILITIES_MASK_ERROR) { - if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] + if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD] & OSC_QUERY_ENABLE) goto out_success; status = AE_SUPPORT; @@ -295,30 +295,30 @@ static void acpi_bus_osc_support(void) }; acpi_handle handle; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; #endif #ifdef ACPI_HOTPLUG_OST - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; #endif if (!ghes_disable) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; - if (context.ret.length > OSC_SUPPORT_TYPE) + if (context.ret.length > OSC_SUPPORT_DWORD) osc_sb_apei_support_acked = - capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT; + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f425653..323afd7ccfbf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -158,14 +158,14 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, support &= OSC_PCI_SUPPORT_MASKS; support |= root->osc_support_set; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = support; + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = support; if (control) { *control &= OSC_PCI_CONTROL_MASKS; - capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; + capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set; } else { /* Run _OSC query only with existing controls. */ - capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; + capbuf[OSC_CONTROL_DWORD] = root->osc_control_set; } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); @@ -357,9 +357,9 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) goto out; } - capbuf[OSC_QUERY_TYPE] = 0; - capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; - capbuf[OSC_CONTROL_TYPE] = ctrl; + capbuf[OSC_QUERY_DWORD] = 0; + capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set; + capbuf[OSC_CONTROL_DWORD] = ctrl; status = acpi_pci_run_osc(handle, capbuf, mask); if (ACPI_SUCCESS(status)) root->osc_control_set = *mask; -- cgit v1.2.3 From 7dab9ef4f0823072a3c9afdb3b373c9f2f38848b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:39 -0600 Subject: PCI/ACPI: Name _OSC #defines more consistently Make PCI Host Bridge _OSC #defines more consistent. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 323afd7ccfbf..28dd55509789 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -49,10 +49,10 @@ static int acpi_pci_root_add(struct acpi_device *device, const struct acpi_device_id *not_used); static void acpi_pci_root_remove(struct acpi_device *device); -#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ - | OSC_ACTIVE_STATE_PWR_SUPPORT \ - | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ - | OSC_MSI_SUPPORT) +#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ + | OSC_PCI_ASPM_SUPPORT \ + | OSC_PCI_CLOCK_PM_SUPPORT \ + | OSC_PCI_MSI_SUPPORT) static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, @@ -439,13 +439,12 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_pci_osc_support(root, flags); if (pci_ext_cfg_avail()) - flags |= OSC_EXT_PCI_CONFIG_SUPPORT; + flags |= OSC_PCI_EXT_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) { - flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + flags |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; } if (pci_msi_enabled()) - flags |= OSC_MSI_SUPPORT; + flags |= OSC_PCI_MSI_SUPPORT; if (flags != base_flags) { status = acpi_pci_osc_support(root, flags); if (ACPI_FAILURE(status)) { @@ -458,7 +457,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + flags = OSC_PCI_EXPRESS_CAPABILITY_CONTROL | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_PME_CONTROL; @@ -474,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device, "Requesting ACPI _OSC control (0x%02x)\n", flags); status = acpi_pci_osc_control_set(handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + OSC_PCI_EXPRESS_CAPABILITY_CONTROL); if (ACPI_SUCCESS(status)) { dev_info(&device->dev, "ACPI _OSC control (0x%02x) granted\n", flags); -- cgit v1.2.3 From 4ffe6e54b0ce259d254e7740a7a4a99dad14a484 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:41 -0600 Subject: PCI/ACPI: Drop unnecessary _OSC existence tests There's no need to check whether _OSC exists here; we eventually call acpi_evaluate_object(..., "_OSC", ...), and that will fail gracefully if _OSC doesn't exist. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 28dd55509789..cc87cc4fea0e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -180,11 +180,7 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) { acpi_status status; - acpi_handle tmp; - status = acpi_get_handle(root->device->handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) - return status; mutex_lock(&osc_lock); status = acpi_pci_query_osc(root, flags, NULL); mutex_unlock(&osc_lock); @@ -316,9 +312,8 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev); acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) { struct acpi_pci_root *root; - acpi_status status; + acpi_status status = AE_OK; u32 ctrl, capbuf[3]; - acpi_handle tmp; if (!mask) return AE_BAD_PARAMETER; @@ -331,10 +326,6 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) if (!root) return AE_NOT_EXIST; - status = acpi_get_handle(handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) - return status; - mutex_lock(&osc_lock); *mask = ctrl | root->osc_control_set; -- cgit v1.2.3 From 3e43abb012d45dc284ef9a0fb0cea0fb004b5607 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:41 -0600 Subject: PCI/ACPI: Move _OSC stuff from acpi_pci_root_add() to negotiate_os_control() This doesn't change any of the _OSC code; it just moves it out into a new function so it doesn't clutter acpi_pci_root_add() so much. This also enables future simplifications. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 132 ++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 61 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index cc87cc4fea0e..3e57f104e09a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -360,67 +360,13 @@ out: } EXPORT_SYMBOL(acpi_pci_osc_control_set); -static int acpi_pci_root_add(struct acpi_device *device, - const struct acpi_device_id *not_used) +static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, + int *clear_aspm) { - unsigned long long segment, bus; - acpi_status status; - int result; - struct acpi_pci_root *root; u32 flags, base_flags; + acpi_status status; + struct acpi_device *device = root->device; acpi_handle handle = device->handle; - bool no_aspm = false, clear_aspm = false; - - root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); - if (!root) - return -ENOMEM; - - segment = 0; - status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, - &segment); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - dev_err(&device->dev, "can't evaluate _SEG\n"); - result = -ENODEV; - goto end; - } - - /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ - root->secondary.flags = IORESOURCE_BUS; - status = try_get_root_bridge_busnr(handle, &root->secondary); - if (ACPI_FAILURE(status)) { - /* - * We need both the start and end of the downstream bus range - * to interpret _CBA (MMCONFIG base address), so it really is - * supposed to be in _CRS. If we don't find it there, all we - * can do is assume [_BBN-0xFF] or [0-0xFF]. - */ - root->secondary.end = 0xFF; - dev_warn(&device->dev, - FW_BUG "no secondary bus range in _CRS\n"); - status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, - NULL, &bus); - if (ACPI_SUCCESS(status)) - root->secondary.start = bus; - else if (status == AE_NOT_FOUND) - root->secondary.start = 0; - else { - dev_err(&device->dev, "can't evaluate _BBN\n"); - result = -ENODEV; - goto end; - } - } - - root->device = device; - root->segment = segment & 0xFFFF; - strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); - device->driver_data = root; - - pr_info(PREFIX "%s [%s] (domain %04x %pR)\n", - acpi_device_name(device), acpi_device_bid(device), - root->segment, &root->secondary); - - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle); /* * All supported architectures that use ACPI have support for @@ -441,7 +387,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (ACPI_FAILURE(status)) { dev_info(&device->dev, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); - no_aspm = true; + *no_aspm = 1; flags = base_flags; } } @@ -473,7 +419,7 @@ static int acpi_pci_root_add(struct acpi_device *device, * We have ASPM control, but the FADT indicates * that it's unsupported. Clear it. */ - clear_aspm = true; + *clear_aspm = 1; } } else { dev_info(&device->dev, @@ -489,13 +435,77 @@ static int acpi_pci_root_add(struct acpi_device *device, * flag here, to defer the action until after the ACPI * root scan. */ - no_aspm = true; + *no_aspm = 1; } } else { dev_info(&device->dev, "Unable to request _OSC control " "(_OSC support mask: 0x%02x)\n", flags); } +} + +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used) +{ + unsigned long long segment, bus; + acpi_status status; + int result; + struct acpi_pci_root *root; + acpi_handle handle = device->handle; + int no_aspm = 0, clear_aspm = 0; + + root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); + if (!root) + return -ENOMEM; + + segment = 0; + status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, + &segment); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + dev_err(&device->dev, "can't evaluate _SEG\n"); + result = -ENODEV; + goto end; + } + + /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ + root->secondary.flags = IORESOURCE_BUS; + status = try_get_root_bridge_busnr(handle, &root->secondary); + if (ACPI_FAILURE(status)) { + /* + * We need both the start and end of the downstream bus range + * to interpret _CBA (MMCONFIG base address), so it really is + * supposed to be in _CRS. If we don't find it there, all we + * can do is assume [_BBN-0xFF] or [0-0xFF]. + */ + root->secondary.end = 0xFF; + dev_warn(&device->dev, + FW_BUG "no secondary bus range in _CRS\n"); + status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, + NULL, &bus); + if (ACPI_SUCCESS(status)) + root->secondary.start = bus; + else if (status == AE_NOT_FOUND) + root->secondary.start = 0; + else { + dev_err(&device->dev, "can't evaluate _BBN\n"); + result = -ENODEV; + goto end; + } + } + + root->device = device; + root->segment = segment & 0xFFFF; + strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); + device->driver_data = root; + + pr_info(PREFIX "%s [%s] (domain %04x %pR)\n", + acpi_device_name(device), acpi_device_bid(device), + root->segment, &root->secondary); + + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle); + + negotiate_os_control(root, &no_aspm, &clear_aspm); /* * TBD: Need PCI interface for enumeration/configuration of roots. -- cgit v1.2.3 From b8eb67fcc4548b9f0d00bbfd1c0c8f72d8018900 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:42 -0600 Subject: PCI/ACPI: Split _OSC "support" and "control" flags into separate variables Previously we used "flags" for both: - the bitmask of features we support (segments, ASPM, MSI, etc.), and - the bitmask of features we want to control (native hotplug, AER, etc.) To reduce confusion, this patch splits this into two variables: "support" is the bitmask of features we support, and "control" is the bitmask of features we want to control. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 3e57f104e09a..3e06d4e179ec 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -363,7 +363,7 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, int *clear_aspm) { - u32 flags, base_flags; + u32 support, base_support, control; acpi_status status; struct acpi_device *device = root->device; acpi_handle handle = device->handle; @@ -372,29 +372,29 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, * All supported architectures that use ACPI have support for * PCI domains, so we indicate this in _OSC support capabilities. */ - flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; - acpi_pci_osc_support(root, flags); + support = base_support = OSC_PCI_SEGMENT_GROUPS_SUPPORT; + acpi_pci_osc_support(root, support); if (pci_ext_cfg_avail()) - flags |= OSC_PCI_EXT_CONFIG_SUPPORT; + support |= OSC_PCI_EXT_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) { - flags |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; + support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; } if (pci_msi_enabled()) - flags |= OSC_PCI_MSI_SUPPORT; - if (flags != base_flags) { - status = acpi_pci_osc_support(root, flags); + support |= OSC_PCI_MSI_SUPPORT; + if (support != base_support) { + status = acpi_pci_osc_support(root, support); if (ACPI_FAILURE(status)) { dev_info(&device->dev, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); *no_aspm = 1; - flags = base_flags; + support = base_support; } } if (!pcie_ports_disabled - && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { - flags = OSC_PCI_EXPRESS_CAPABILITY_CONTROL + && (support & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { + control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_PME_CONTROL; @@ -403,17 +403,18 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, dev_dbg(&device->dev, "PCIe errors handled by BIOS.\n"); else - flags |= OSC_PCI_EXPRESS_AER_CONTROL; + control |= OSC_PCI_EXPRESS_AER_CONTROL; } dev_info(&device->dev, - "Requesting ACPI _OSC control (0x%02x)\n", flags); + "Requesting ACPI _OSC control (0x%02x)\n", control); - status = acpi_pci_osc_control_set(handle, &flags, + status = acpi_pci_osc_control_set(handle, &control, OSC_PCI_EXPRESS_CAPABILITY_CONTROL); if (ACPI_SUCCESS(status)) { dev_info(&device->dev, - "ACPI _OSC control (0x%02x) granted\n", flags); + "ACPI _OSC control (0x%02x) granted\n", + control); if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { /* * We have ASPM control, but the FADT indicates @@ -425,7 +426,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, dev_info(&device->dev, "ACPI _OSC request failed (%s), " "returned control mask: 0x%02x\n", - acpi_format_exception(status), flags); + acpi_format_exception(status), control); dev_info(&device->dev, "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); /* @@ -440,7 +441,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, } else { dev_info(&device->dev, "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", flags); + "(_OSC support mask: 0x%02x)\n", support); } } -- cgit v1.2.3 From 1b2a7be60eaaf17bc88368d748471dd70e40befd Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:42 -0600 Subject: PCI/ACPI: Run _OSC only once for OSPM feature support Previously, we ran _OSC once to tell the platform that we support PCI Segment Groups, then we ran it again if we supported any additional features (ASPM, MSI, or extended config space). I don't think it's necessary to run it twice, since we can easily build the complete mask of features we support before running _OSC the first time. We run _OSC again later when requesting control of PCIe features; that's unaffected by this change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 3e06d4e179ec..0e2004100c44 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -373,23 +373,18 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, * PCI domains, so we indicate this in _OSC support capabilities. */ support = base_support = OSC_PCI_SEGMENT_GROUPS_SUPPORT; - acpi_pci_osc_support(root, support); - if (pci_ext_cfg_avail()) support |= OSC_PCI_EXT_CONFIG_SUPPORT; - if (pcie_aspm_support_enabled()) { + if (pcie_aspm_support_enabled()) support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; - } if (pci_msi_enabled()) support |= OSC_PCI_MSI_SUPPORT; - if (support != base_support) { - status = acpi_pci_osc_support(root, support); - if (ACPI_FAILURE(status)) { - dev_info(&device->dev, "ACPI _OSC support " - "notification failed, disabling PCIe ASPM\n"); - *no_aspm = 1; - support = base_support; - } + status = acpi_pci_osc_support(root, support); + if (ACPI_FAILURE(status)) { + dev_info(&device->dev, "ACPI _OSC support " + "notification failed, disabling PCIe ASPM\n"); + *no_aspm = 1; + support = base_support; } if (!pcie_ports_disabled -- cgit v1.2.3 From 65afe91622c456560e20d57a779b807c20822e81 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:43 -0600 Subject: PCI/ACPI: Skip _OSC control tests if _OSC support call failed If the _OSC support notification fails, we will never request control (because "support == OSC_PCI_SEGMENT_GROUPS_SUPPORT", which doesn't include all the features in ACPI_PCIE_REQ_SUPPORT), so we can return early to simplify the code. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0e2004100c44..67cc43a134ad 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -363,7 +363,7 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, int *clear_aspm) { - u32 support, base_support, control; + u32 support, control; acpi_status status; struct acpi_device *device = root->device; acpi_handle handle = device->handle; @@ -372,7 +372,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, * All supported architectures that use ACPI have support for * PCI domains, so we indicate this in _OSC support capabilities. */ - support = base_support = OSC_PCI_SEGMENT_GROUPS_SUPPORT; + support = OSC_PCI_SEGMENT_GROUPS_SUPPORT; if (pci_ext_cfg_avail()) support |= OSC_PCI_EXT_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) @@ -381,10 +381,10 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, support |= OSC_PCI_MSI_SUPPORT; status = acpi_pci_osc_support(root, support); if (ACPI_FAILURE(status)) { - dev_info(&device->dev, "ACPI _OSC support " - "notification failed, disabling PCIe ASPM\n"); + dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n", + acpi_format_exception(status)); *no_aspm = 1; - support = base_support; + return; } if (!pcie_ports_disabled -- cgit v1.2.3 From 43613a1fac0eec78de14fecc9de184e1052abac7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:43 -0600 Subject: PCI/ACPI: Separate out _OSC "PCIe port services disabled" path Test "pcie_ports_disabled" separately so we can give a better message. Previously we said "Unable to request _OSC control..."; now we'll say "PCIe port services disabled; not requesting _OSC control". "pcie_ports_disabled" is true when CONFIG_PCIEPORTBUS=n or we boot with "pcie_ports=compat". Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 67cc43a134ad..68e5a187e784 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -387,8 +387,12 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, return; } - if (!pcie_ports_disabled - && (support & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { + if (pcie_ports_disabled) { + dev_info(&device->dev, "PCIe port services disabled; not requesting _OSC control\n"); + return; + } + + if ((support & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_PME_CONTROL; -- cgit v1.2.3 From de18966228ed4b42393ecbe83ba20ff3db78bfdc Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:50:52 -0600 Subject: PCI/ACPI: Separate out _OSC "we don't support enough services" path Test the services we support (extended config space, ASPM, MSI) separately so we can give a better message. Previously we said "Unable to request _OSC control..."; now we'll say "we support %#02x but %#02x are required". Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 84 ++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 68e5a187e784..65aefcf78552 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -392,55 +392,55 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, return; } - if ((support & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { - control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL - | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL - | OSC_PCI_EXPRESS_PME_CONTROL; - - if (pci_aer_available()) { - if (aer_acpi_firmware_first()) - dev_dbg(&device->dev, - "PCIe errors handled by BIOS.\n"); - else - control |= OSC_PCI_EXPRESS_AER_CONTROL; - } + if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) { + dev_info(&device->dev, "Not requesting _OSC control (we support %#02x but %#02x are required)\n", + support, ACPI_PCIE_REQ_SUPPORT); + return; + } + + control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL + | OSC_PCI_EXPRESS_PME_CONTROL; + + if (pci_aer_available()) { + if (aer_acpi_firmware_first()) + dev_dbg(&device->dev, + "PCIe errors handled by BIOS.\n"); + else + control |= OSC_PCI_EXPRESS_AER_CONTROL; + } + dev_info(&device->dev, + "Requesting ACPI _OSC control (0x%02x)\n", control); + + status = acpi_pci_osc_control_set(handle, &control, + OSC_PCI_EXPRESS_CAPABILITY_CONTROL); + if (ACPI_SUCCESS(status)) { dev_info(&device->dev, - "Requesting ACPI _OSC control (0x%02x)\n", control); - - status = acpi_pci_osc_control_set(handle, &control, - OSC_PCI_EXPRESS_CAPABILITY_CONTROL); - if (ACPI_SUCCESS(status)) { - dev_info(&device->dev, - "ACPI _OSC control (0x%02x) granted\n", - control); - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - /* - * We have ASPM control, but the FADT indicates - * that it's unsupported. Clear it. - */ - *clear_aspm = 1; - } - } else { - dev_info(&device->dev, - "ACPI _OSC request failed (%s), " - "returned control mask: 0x%02x\n", - acpi_format_exception(status), control); - dev_info(&device->dev, - "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); + "ACPI _OSC control (0x%02x) granted\n", + control); + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { /* - * We want to disable ASPM here, but aspm_disabled - * needs to remain in its state from boot so that we - * properly handle PCIe 1.1 devices. So we set this - * flag here, to defer the action until after the ACPI - * root scan. + * We have ASPM control, but the FADT indicates + * that it's unsupported. Clear it. */ - *no_aspm = 1; + *clear_aspm = 1; } } else { dev_info(&device->dev, - "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", support); + "ACPI _OSC request failed (%s), " + "returned control mask: 0x%02x\n", + acpi_format_exception(status), control); + dev_info(&device->dev, + "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); + /* + * We want to disable ASPM here, but aspm_disabled + * needs to remain in its state from boot so that we + * properly handle PCIe 1.1 devices. So we set this + * flag here, to defer the action until after the ACPI + * root scan. + */ + *no_aspm = 1; } } -- cgit v1.2.3 From 955f14b4ed0648da12f0a7011f94150b8982a5c2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:45 -0600 Subject: PCI/ACPI: Decode _OSC bitmasks symbolically This updates _OSC-related messages to be more human-readable. We now always show the features we declare support for (this was previously invisible) as well as the features we are granted control of. Typical changes: -acpi PNP0A08:00: Requesting ACPI _OSC control (0x1d) -acpi PNP0A08:00: ACPI _OSC control (0x1d) granted +acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI] +acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME AER PCIeCapability] Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 84 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 65aefcf78552..924ad92852c1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -127,6 +127,55 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, return AE_OK; } +struct pci_osc_bit_struct { + u32 bit; + char *desc; +}; + +static struct pci_osc_bit_struct pci_osc_support_bit[] = { + { OSC_PCI_EXT_CONFIG_SUPPORT, "ExtendedConfig" }, + { OSC_PCI_ASPM_SUPPORT, "ASPM" }, + { OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" }, + { OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" }, + { OSC_PCI_MSI_SUPPORT, "MSI" }, +}; + +static struct pci_osc_bit_struct pci_osc_control_bit[] = { + { OSC_PCI_EXPRESS_NATIVE_HP_CONTROL, "PCIeHotplug" }, + { OSC_PCI_SHPC_NATIVE_HP_CONTROL, "SHPCHotplug" }, + { OSC_PCI_EXPRESS_PME_CONTROL, "PME" }, + { OSC_PCI_EXPRESS_AER_CONTROL, "AER" }, + { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" }, +}; + +static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word, + struct pci_osc_bit_struct *table, int size) +{ + char buf[80]; + int i, len = 0; + struct pci_osc_bit_struct *entry; + + buf[0] = '\0'; + for (i = 0, entry = table; i < size; i++, entry++) + if (word & entry->bit) + len += snprintf(buf + len, sizeof(buf) - len, "%s%s", + len ? " " : "", entry->desc); + + dev_info(&root->device->dev, "_OSC: %s [%s]\n", msg, buf); +} + +static void decode_osc_support(struct acpi_pci_root *root, char *msg, u32 word) +{ + decode_osc_bits(root, msg, word, pci_osc_support_bit, + ARRAY_SIZE(pci_osc_support_bit)); +} + +static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word) +{ + decode_osc_bits(root, msg, word, pci_osc_control_bit, + ARRAY_SIZE(pci_osc_control_bit)); +} + static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -340,10 +389,14 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) goto out; if (ctrl == *mask) break; + decode_osc_control(root, "platform does not support", + ctrl & ~(*mask)); ctrl = *mask; } if ((ctrl & req) != req) { + decode_osc_control(root, "not requesting control; platform does not support", + req & ~(ctrl)); status = AE_SUPPORT; goto out; } @@ -363,7 +416,7 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, int *clear_aspm) { - u32 support, control; + u32 support, control, requested; acpi_status status; struct acpi_device *device = root->device; acpi_handle handle = device->handle; @@ -379,6 +432,8 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; if (pci_msi_enabled()) support |= OSC_PCI_MSI_SUPPORT; + + decode_osc_support(root, "OS supports", support); status = acpi_pci_osc_support(root, support); if (ACPI_FAILURE(status)) { dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n", @@ -393,8 +448,8 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, } if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) { - dev_info(&device->dev, "Not requesting _OSC control (we support %#02x but %#02x are required)\n", - support, ACPI_PCIE_REQ_SUPPORT); + decode_osc_support(root, "not requesting OS control; OS requires", + ACPI_PCIE_REQ_SUPPORT); return; } @@ -404,21 +459,17 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, if (pci_aer_available()) { if (aer_acpi_firmware_first()) - dev_dbg(&device->dev, - "PCIe errors handled by BIOS.\n"); + dev_info(&device->dev, + "PCIe AER handled by firmware\n"); else control |= OSC_PCI_EXPRESS_AER_CONTROL; } - dev_info(&device->dev, - "Requesting ACPI _OSC control (0x%02x)\n", control); - + requested = control; status = acpi_pci_osc_control_set(handle, &control, OSC_PCI_EXPRESS_CAPABILITY_CONTROL); if (ACPI_SUCCESS(status)) { - dev_info(&device->dev, - "ACPI _OSC control (0x%02x) granted\n", - control); + decode_osc_control(root, "OS now controls", control); if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { /* * We have ASPM control, but the FADT indicates @@ -427,12 +478,11 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, *clear_aspm = 1; } } else { - dev_info(&device->dev, - "ACPI _OSC request failed (%s), " - "returned control mask: 0x%02x\n", - acpi_format_exception(status), control); - dev_info(&device->dev, - "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); + decode_osc_control(root, "OS requested", requested); + decode_osc_control(root, "platform willing to grant", control); + dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n", + acpi_format_exception(status)); + /* * We want to disable ASPM here, but aspm_disabled * needs to remain in its state from boot so that we -- cgit v1.2.3 From f28eb9f5009abdc74d4052ae05c01795e254a6fc Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:13 +0800 Subject: ACPICA: Improve error message for "too many parent prefixes" condition. Emit the full offending pathname in the error message. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsaccess.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index c5316e5bd4ab..aff79c7392ff 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) " - "- reached beyond root node")); + "%s: Path has too many parent prefixes (^) " + "- reached beyond root node", + pathname)); return_ACPI_STATUS(AE_NOT_FOUND); } } -- cgit v1.2.3 From c3faedcdb41a2fedbec8ca8f8612d67b012b44a2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 23 Sep 2013 09:51:22 +0800 Subject: ACPICA: acpi_read: On error, do not modify the return value target location. If an error happens in the middle of a split 32/32 64-bit I/O operation, do not modify the target of the return value pointer. Makes the code consistent with the rest of ACPICA. Bjorn Helgaas. Signed-off-by: Bjorn Helgaas Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwxface.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 5ee7a814cd92..f81fb068d20e 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -119,7 +119,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset) ******************************************************************************/ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) { - u32 value; + u32 value_lo; + u32 value_hi; u32 width; u64 address; acpi_status status; @@ -137,13 +138,8 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) return (status); } - /* Initialize entire 64-bit return value to zero */ - - *return_value = 0; - value = 0; - /* - * Two address spaces supported: Memory or IO. PCI_Config is + * Two address spaces supported: Memory or I/O. PCI_Config is * not supported here because the GAS structure is insufficient */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { @@ -155,29 +151,35 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) } } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + value_lo = 0; + value_hi = 0; + width = reg->bit_width; if (width == 64) { width = 32; /* Break into two 32-bit transfers */ } status = acpi_hw_read_port((acpi_io_address) - address, &value, width); + address, &value_lo, width); if (ACPI_FAILURE(status)) { return (status); } - *return_value = value; if (reg->bit_width == 64) { /* Read the top 32 bits */ status = acpi_hw_read_port((acpi_io_address) - (address + 4), &value, 32); + (address + 4), &value_hi, + 32); if (ACPI_FAILURE(status)) { return (status); } - *return_value |= ((u64)value << 32); } + + /* Set the return value only if status is AE_OK */ + + *return_value = (value_lo | ((u64)value_hi << 32)); } ACPI_DEBUG_PRINT((ACPI_DB_IO, @@ -186,7 +188,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); - return (status); + return (AE_OK); } ACPI_EXPORT_SYMBOL(acpi_read) -- cgit v1.2.3 From 2856846e3a7bee02ce6b498c760376061e41aaed Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:39 +0800 Subject: ACPICA: Debug output: small formatting update, no functional change. Allow for longer filenames in the module name output during trace operations. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utdebug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 5796e11a0671..ffd0db509d34 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -190,7 +190,7 @@ acpi_debug_print(u32 requested_debug_level, * Display the module name, current line number, thread ID (if requested), * current procedure nesting level, and the current procedure name */ - acpi_os_printf("%8s-%04ld ", module_name, line_number); + acpi_os_printf("%9s-%04ld ", module_name, line_number); if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf("[%u] ", (u32)thread_id); -- cgit v1.2.3 From 1f5210a1e6c21ef850a290bac2a85ae1da2f0c2e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:52 +0800 Subject: ACPICA: Debugger: Prevent possible command line buffer overflow, kernel behavior is not affected. Increase the size of a couple of the debugger line buffers. ACPICA BZ 1037. The debugger related code is not in the kernel so the behavior of the kernel is not affected. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1037 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 90e846f985fa..c9ad2e1f1ee1 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -445,13 +445,6 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_tables; ACPI_EXTERN u8 acpi_gbl_db_opt_stats; ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support; - -ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_scope_buf[80]; -ACPI_EXTERN char acpi_gbl_db_debug_filename[80]; ACPI_EXTERN u8 acpi_gbl_db_output_to_file; ACPI_EXTERN char *acpi_gbl_db_buffer; ACPI_EXTERN char *acpi_gbl_db_filename; @@ -459,6 +452,16 @@ ACPI_EXTERN u32 acpi_gbl_db_debug_level; ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; +ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; + +/* These buffers should all be the same size */ + +ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]; + /* * Statistic globals */ -- cgit v1.2.3 From d53d820741806a5488d0f002b61765deb58371f3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:58 +0800 Subject: ACPICA: Validate start object for acpi_walk_namespace. Perform a sanity check on the start object to prevent problems later. ACPICA BZ 1025. This patch only adds additional input parameter validation, no actual kernel suffering has been discovered. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1025 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsxfeval.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index b38b4b07f86e..481a6b4a9b2f 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -605,11 +605,19 @@ acpi_walk_namespace(acpi_object_type type, goto unlock_and_exit; } + /* Now we can validate the starting node */ + + if (!acpi_ns_validate_handle(start_object)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit2; + } + status = acpi_ns_walk_namespace(type, start_object, max_depth, ACPI_NS_WALK_UNLOCK, descending_callback, ascending_callback, context, return_value); + unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); unlock_and_exit: -- cgit v1.2.3 From a2fd4b4b4e2884405c54a91514b0fad3853aea01 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:05 +0800 Subject: ACPICA: Add support for host-installed SCI handlers. This change adds support to allow hosts to install System Control Interrupt handlers. Certain ACPI functionality requires the host to handle raw SCIs. For example, the "SCI Doorbell" that is defined for memory power state support requires the host device driver to handle SCIs to examine if the doorbell has been activated. Multiple SCI handlers can be installed to allow for future expansion. Debugger support is included. Lv Zheng, Bob Moore. ACPICA BZ 1032. Bug summary: It is reported when the PCC (Platform Communication Channel, via MPST table, defined in ACPI specification 5.0) subchannel responds to the host, it issues an SCI and the host must probe the subchannel for channel status. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1032 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 3 +- drivers/acpi/acpica/acevents.h | 6 +- drivers/acpi/acpica/acglobal.h | 1 + drivers/acpi/acpica/aclocal.h | 8 +++ drivers/acpi/acpica/evgpeutil.c | 2 +- drivers/acpi/acpica/evmisc.c | 14 ++-- drivers/acpi/acpica/evsci.c | 80 +++++++++++++++++++++-- drivers/acpi/acpica/evxface.c | 139 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utglobal.c | 3 +- 9 files changed, 236 insertions(+), 20 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 9feba08c29fe..30c2d6911386 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -113,11 +113,12 @@ void acpi_db_display_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) + ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) /* * dbconvert - miscellaneous conversion routines */ - acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); +acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index ab0e97710381..3ae5fd02ae64 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, */ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context); -u32 acpi_ev_install_sci_handler(void); +u32 acpi_ev_sci_dispatch(void); -acpi_status acpi_ev_remove_sci_handler(void); +u32 acpi_ev_install_sci_handler(void); -u32 acpi_ev_initialize_SCI(u32 program_SCI); +acpi_status acpi_ev_remove_all_sci_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void)) #endif /* __ACEVENTS_H__ */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index c9ad2e1f1ee1..0fba431f4fcb 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler; ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; +ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list; /* Owner ID support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0ed00669cd21..be9e30ee6048 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -398,6 +398,14 @@ struct acpi_simple_repair_info { * ****************************************************************************/ +/* Dispatch info for each host-installed SCI handler */ + +struct acpi_sci_handler_info { + struct acpi_sci_handler_info *next; + acpi_sci_handler address; /* Address of handler */ + void *context; /* Context to be passed to handler */ +}; + /* Dispatch info for each GPE -- either a method or handler, cannot be both */ struct acpi_gpe_handler_info { diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index b24dbb80fab8..d52339090b60 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * * FUNCTION: acpi_ev_get_gpe_xrupt_block * - * PARAMETERS: interrupt_number - Interrupt for a GPE block + * PARAMETERS: interrupt_number - Interrupt for a GPE block * * RETURN: A GPE interrupt block * diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 1b111ef74903..a5687540e9a6 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -264,13 +264,6 @@ void acpi_ev_terminate(void) status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - /* Remove SCI handler */ - - status = acpi_ev_remove_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); - } - status = acpi_ev_remove_global_lock_handler(); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, @@ -280,6 +273,13 @@ void acpi_ev_terminate(void) acpi_gbl_events_initialized = FALSE; } + /* Remove SCI handlers */ + + status = acpi_ev_remove_all_sci_handlers(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); + } + /* Deallocate all handler objects installed within GPE info structs */ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b905acf7aacd..b2f0fb2f57b4 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -52,6 +52,52 @@ ACPI_MODULE_NAME("evsci") /* Local prototypes */ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); +/******************************************************************************* + * + * FUNCTION: acpi_ev_sci_dispatch + * + * PARAMETERS: None + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. + * + ******************************************************************************/ + +u32 acpi_ev_sci_dispatch(void) +{ + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_NAME(ev_sci_dispatch); + + /* Are there any host-installed SCI handlers? */ + + if (!acpi_gbl_sci_handler_list) { + return (int_status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Invoke all host-installed SCI handlers */ + + sci_handler = acpi_gbl_sci_handler_list; + while (sci_handler) { + + /* Invoke the installed handler (at interrupt level) */ + + int_status |= sci_handler->address((u32)acpi_gbl_FADT. + sci_interrupt, + sci_handler->context); + + sci_handler = sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return (int_status); +} + /******************************************************************************* * * FUNCTION: acpi_ev_sci_xrupt_handler @@ -89,6 +135,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + /* Invoke all host-installed SCI handlers */ + + interrupt_handled |= acpi_ev_sci_dispatch(); + return_UINT32(interrupt_handled); } @@ -112,14 +162,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* - * We are guaranteed by the ACPI CA initialization/shutdown code that + * We are guaranteed by the ACPICA initialization/shutdown code that * if this interrupt handler is installed, ACPI is enabled. */ /* GPEs: Check for and dispatch any GPEs that have occurred */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); } @@ -150,15 +199,15 @@ u32 acpi_ev_install_sci_handler(void) /****************************************************************************** * - * FUNCTION: acpi_ev_remove_sci_handler + * FUNCTION: acpi_ev_remove_all_sci_handlers * * PARAMETERS: none * - * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not * installed to begin with * * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be - * taken. + * taken. Remove all host-installed SCI handlers. * * Note: It doesn't seem important to disable all events or set the event * enable registers to their original values. The OS should disable @@ -167,11 +216,13 @@ u32 acpi_ev_install_sci_handler(void) * ******************************************************************************/ -acpi_status acpi_ev_remove_sci_handler(void) +acpi_status acpi_ev_remove_all_sci_handlers(void) { + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; acpi_status status; - ACPI_FUNCTION_TRACE(ev_remove_sci_handler); + ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers); /* Just let the OS remove the handler and disable the level */ @@ -179,6 +230,21 @@ acpi_status acpi_ev_remove_sci_handler(void) acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, acpi_ev_sci_xrupt_handler); + if (!acpi_gbl_sci_handler_list) { + return (status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Free all host-installed SCI handlers */ + + while (acpi_gbl_sci_handler_list) { + sci_handler = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = sci_handler->next; + ACPI_FREE(sci_handler); + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index ca5fba99c33b..6f56146a6f88 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -383,6 +383,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ #if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: acpi_install_sci_handler + * + * PARAMETERS: address - Address of the handler + * context - Value passed to the handler on each SCI + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a System Control Interrupt. + * + ******************************************************************************/ +acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) +{ + struct acpi_sci_handler_info *new_sci_handler; + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Allocate and init a handler object */ + + new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info)); + if (!new_sci_handler) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_sci_handler->address = address; + new_sci_handler->context = context; + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Lock list during installation */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + sci_handler = acpi_gbl_sci_handler_list; + + /* Ensure handler does not already exist */ + + while (sci_handler) { + if (address == sci_handler->address) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + sci_handler = sci_handler->next; + } + + /* Install the new handler into the global list (at head) */ + + new_sci_handler->next = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = new_sci_handler; + + unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + exit: + if (ACPI_FAILURE(status)) { + ACPI_FREE(new_sci_handler); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_remove_sci_handler + * + * PARAMETERS: address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a System Control Interrupt. + * + ******************************************************************************/ + +acpi_status acpi_remove_sci_handler(acpi_sci_handler address) +{ + struct acpi_sci_handler_info *prev_sci_handler; + struct acpi_sci_handler_info *next_sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Remove the SCI handler with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + prev_sci_handler = NULL; + next_sci_handler = acpi_gbl_sci_handler_list; + while (next_sci_handler) { + if (next_sci_handler->address == address) { + + /* Unlink and free the SCI handler info block */ + + if (prev_sci_handler) { + prev_sci_handler->next = next_sci_handler->next; + } else { + acpi_gbl_sci_handler_list = + next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + ACPI_FREE(next_sci_handler); + goto unlock_and_exit; + } + + prev_sci_handler = next_sci_handler; + next_sci_handler = next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + status = AE_NOT_EXIST; + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_install_global_event_handler @@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) * Can be used to update event counters, etc. * ******************************************************************************/ + acpi_status acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d6f26bf8a062..046d5b059c07 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void) #if (!ACPI_REDUCED_HARDWARE) - /* GPE support */ + /* GPE/SCI support */ acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; @@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void) acpi_current_gpe_count = 0; acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; #endif /* !ACPI_REDUCED_HARDWARE */ -- cgit v1.2.3 From d2e7d079c7f21999e93802351c6ac7b31d266cce Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Mon, 23 Sep 2013 09:52:12 +0800 Subject: ACPICA: Operation region support: Never free the handler "context" pointer. This change removes some dangerous code that attempts to free the handler context pointer in some (rare) circumstances. The owner of the handler owns this pointer and the ACPICA code should never touch it. Although not seen to be an issue in any kernel, it did show up as a problem under AcpiExec. Also, set the internal storage field for the context pointer to zero when the region is deactivated, simply for sanity. David Box. Signed-off-by: David E. Box Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evregion.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index cea14d6fc76c..6293d6bb6fe1 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -217,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - if (region_obj2->extra.region_context) { - - /* The handler for this region was already installed */ - - ACPI_FREE(region_context); - } else { - /* - * Save the returned context for use in all accesses to - * this particular region - */ + /* + * Save the returned context for use in all accesses to + * the handler for this particular region + */ + if (!(region_obj2->extra.region_context)) { region_obj2->extra.region_context = region_context; } @@ -402,6 +397,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, handler_obj->address_space. context, region_context); + /* + * region_context should have been released by the deactivate + * operation. We don't need access to it anymore here. + */ + if (region_context) { + *region_context = NULL; + } + /* Init routine may fail, Just ignore errors */ if (ACPI_FAILURE(status)) { -- cgit v1.2.3 From 424deb3870580d9afbbb421edfbe30a02ef28056 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:19 +0800 Subject: ACPICA: Debugger: Add new command to display full namespace pathnames. Paths command displays the full pathname and object type for the entire namespace. Alternative to the Namespace command. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 2 + drivers/acpi/acpica/acnamesp.h | 6 ++ drivers/acpi/acpica/nsdump.c | 134 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 30c2d6911386..27c36a5251b5 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -155,6 +155,8 @@ void acpi_db_set_scope(char *name); void acpi_db_dump_namespace(char *start_arg, char *depth_arg); +void acpi_db_dump_namespace_paths(void); + void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); acpi_status acpi_db_find_name_in_namespace(char *name_arg); diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 40b04bd5579e..e6138ac4a160 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -213,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type, u8 display_type, u32 max_depth, acpi_owner_id owner_id, acpi_handle start_handle); + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle); #endif /* ACPI_FUTURE_USAGE */ /* diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 7418c77fde8c..80633851cb2f 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -59,6 +59,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, #endif #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#ifdef ACPI_FUTURE_USAGE +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value); +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_print_pathname @@ -671,6 +682,129 @@ acpi_ns_dump_objects(acpi_object_type type, } #endif /* ACPI_FUTURE_USAGE */ +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth + * + * PARAMETERS: obj_handle - Node to be dumped + * level - Nesting level of the handle + * context - Passed into walk_namespace + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth + * computes the maximum nesting depth in the namespace tree, in + * order to simplify formatting in acpi_ns_dump_one_object_path. + * These procedures are user_functions called by acpi_ns_walk_namespace. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 max_level = *((u32 *)context); + char *pathname; + struct acpi_namespace_node *node; + int path_indent; + + if (!obj_handle) { + return (AE_OK); + } + + node = acpi_ns_validate_handle(obj_handle); + pathname = acpi_ns_get_external_pathname(node); + + path_indent = 1; + if (level <= max_level) { + path_indent = max_level - level + 1; + } + + acpi_os_printf("%2d%*s%-12s%*s", + level, level, " ", acpi_ut_get_type_name(node->type), + path_indent, " "); + + acpi_os_printf("%s\n", &pathname[1]); + ACPI_FREE(pathname); + return (AE_OK); +} + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 *max_level = (u32 *)context; + + if (level > *max_level) { + *max_level = level; + } + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_object_paths + * + * PARAMETERS: type - Object type to be dumped + * display_type - 0 or ACPI_DISPLAY_SUMMARY + * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX + * for an effectively unlimited depth. + * owner_id - Dump only objects owned by this ID. Use + * ACPI_UINT32_MAX to match all owners. + * start_handle - Where in namespace to start/end search + * + * RETURN: None + * + * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses + * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path. + * + ******************************************************************************/ + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle) +{ + acpi_status status; + u32 max_level = 0; + + ACPI_FUNCTION_ENTRY(); + + /* + * Just lock the entire namespace for the duration of the dump. + * We don't want any changes to the namespace during this time, + * especially the temporary nodes since we are going to display + * them also. + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not acquire namespace mutex\n"); + return; + } + + /* Get the max depth of the namespace tree, for formatting later */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_get_max_depth, NULL, + (void *)&max_level, NULL); + + /* Now dump the entire namespace */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_dump_one_object_path, NULL, + (void *)&max_level, NULL); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_dump_entry -- cgit v1.2.3 From 94d4be6773e86a0d52d7e200fb3cda2b9013c862 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:29 +0800 Subject: ACPICA: Tables: Cleanup table checksum verification code. This patch reduces code redundancy by moving the FACS/S3PT checksum verification skip logic into acpi_tb_verify_checksum() and other calls of this function also get benefit from this change. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbinstal.c | 12 +++--------- drivers/acpi/acpica/tbprint.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 42a13c0d7015..9e6788f9ba0f 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -80,16 +80,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) } } - /* FACS is the odd table, has no standard ACPI header and no checksum */ + /* Always calculate checksum, ignore bad checksum if requested */ - if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { - - /* Always calculate checksum, ignore bad checksum if requested */ - - status = - acpi_tb_verify_checksum(table_desc->pointer, - table_desc->length); - } + status = + acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index dc963f823d2c..499759a23b41 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -190,6 +190,16 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) { u8 checksum; + /* + * FACS/S3PT: + * They are the odd tables, have no standard ACPI header and no checksum + */ + + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) { + return (AE_OK); + } + /* Compute the checksum on the table */ checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); -- cgit v1.2.3 From cacba8657351f709ab3cb53a2b207f513f14054c Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:34 +0800 Subject: ACPICA: Tables: Cleanup RSDP signature codes. This patch introduces new macors to handle RSDP signature and cleans up the affected codes. Lv Zheng. Some updates are only used for ACPICA utilities which are not shipped in the kernel yet. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbprint.c | 2 +- drivers/acpi/acpica/tbxfroot.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 499759a23b41..9a47715af1f3 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -138,7 +138,7 @@ acpi_tb_print_table_header(acpi_physical_address address, ACPI_INFO((AE_INFO, "%4.4s %p %05X", header->signature, ACPI_CAST_PTR(void, address), header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { /* RSDP has no common fields */ diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 948c95e80d44..1c95fabbe6a4 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP, - sizeof(ACPI_SIG_RSDP) - 1) != 0) { + if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { /* Nope, BAD Signature */ -- cgit v1.2.3 From c53ae3a60c2494a160140d09637f543562626365 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:45 +0800 Subject: ACPICA: SCI Handlers: Update handler interface, eliminate unnecessary argument. The SCI interrupt number is not needed for the SCI handlers, and was just unnecessary overhead. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evsci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b2f0fb2f57b4..94d9ebddf575 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -87,9 +87,7 @@ u32 acpi_ev_sci_dispatch(void) /* Invoke the installed handler (at interrupt level) */ - int_status |= sci_handler->address((u32)acpi_gbl_FADT. - sci_interrupt, - sci_handler->context); + int_status |= sci_handler->address(sci_handler->context); sci_handler = sci_handler->next; } -- cgit v1.2.3 From 06a8566bcf5cf7db9843a82cde7a33c7bf3947d9 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:23 +0800 Subject: ACPI / IPMI: Fix atomic context requirement of ipmi_msg_handler() This patch fixes the issues indicated by the test results that ipmi_msg_handler() is invoked in atomic context. BUG: scheduling while atomic: kipmi0/18933/0x10000100 Modules linked in: ipmi_si acpi_ipmi ... CPU: 3 PID: 18933 Comm: kipmi0 Tainted: G AW 3.10.0-rc7+ #2 Hardware name: QCI QSSC-S4R/QSSC-S4R, BIOS QSSC-S4R.QCI.01.00.0027.070120100606 07/01/2010 ffff8838245eea00 ffff88103fc63c98 ffffffff814c4a1e ffff88103fc63ca8 ffffffff814bfbab ffff88103fc63d28 ffffffff814c73e0 ffff88103933cbd4 0000000000000096 ffff88103fc63ce8 ffff88102f618000 ffff881035c01fd8 Call Trace: [] dump_stack+0x19/0x1b [] __schedule_bug+0x46/0x54 [] __schedule+0x83/0x59c [] __cond_resched+0x22/0x2d [] _cond_resched+0x14/0x1d [] mutex_lock+0x11/0x32 [] ? __default_send_IPI_dest_field.constprop.0+0x53/0x58 [] ipmi_msg_handler+0x23/0x166 [ipmi_si] [] deliver_response+0x55/0x5a [] handle_new_recv_msgs+0xb67/0xc65 [] ? read_tsc+0x9/0x19 [] ? _raw_spin_lock_irq+0xa/0xc [] ipmi_thread+0x5c/0x146 [ipmi_si] ... Also Tony Camuso says: We were getting occasional "Scheduling while atomic" call traces during boot on some systems. Problem was first seen on a Cisco C210 but we were able to reproduce it on a Cisco c220m3. Setting CONFIG_LOCKDEP and LOCKDEP_SUPPORT to 'y' exposed a lockdep around tx_msg_lock in acpi_ipmi.c struct acpi_ipmi_device. ================================= [ INFO: inconsistent lock state ] 2.6.32-415.el6.x86_64-debug-splck #1 --------------------------------- inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. ksoftirqd/3/17 [HC0[0]:SC1[1]:HE1:SE0] takes: (&ipmi_device->tx_msg_lock){+.?...}, at: [] ipmi_msg_handler+0x71/0x126 {SOFTIRQ-ON-W} state was registered at: [] __lock_acquire+0x63c/0x1570 [] lock_acquire+0xa4/0x120 [] __mutex_lock_common+0x4c/0x400 [] mutex_lock_nested+0x4a/0x60 [] acpi_ipmi_space_handler+0x11b/0x234 [] acpi_ev_address_space_dispatch+0x170/0x1be The fix implemented by this change has been tested by Tony: Tested the patch in a boot loop with lockdep debug enabled and never saw the problem in over 400 reboots. Reported-and-tested-by: Tony Camuso Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index f40acef80269..a6977e12d574 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -39,6 +39,7 @@ #include #include #include +#include MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); @@ -57,7 +58,7 @@ struct acpi_ipmi_device { struct list_head head; /* the IPMI request message list */ struct list_head tx_msg_list; - struct mutex tx_msg_lock; + spinlock_t tx_msg_lock; acpi_handle handle; struct pnp_dev *pnp_dev; ipmi_user_t user_interface; @@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, struct kernel_ipmi_msg *msg; struct acpi_ipmi_buffer *buffer; struct acpi_ipmi_device *device; + unsigned long flags; msg = &tx_msg->tx_message; /* @@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, /* Get the msgid */ device = tx_msg->device; - mutex_lock(&device->tx_msg_lock); + spin_lock_irqsave(&device->tx_msg_lock, flags); device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; - mutex_unlock(&device->tx_msg_lock); + spin_unlock_irqrestore(&device->tx_msg_lock, flags); } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, @@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) int msg_found = 0; struct acpi_ipmi_msg *tx_msg; struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; + unsigned long flags; if (msg->user != ipmi_device->user_interface) { dev_warn(&pnp_dev->dev, "Unexpected response is returned. " @@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) ipmi_free_recv_msg(msg); return; } - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { msg_found = 1; @@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } } - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); @@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, struct acpi_ipmi_device *ipmi_device = handler_context; int err, rem_time; acpi_status status; + unsigned long flags; /* * IPMI opregion message. * IPMI message is firstly written to the BMC and system software @@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, return AE_NO_MEMORY; acpi_format_ipmi_msg(tx_msg, address, value); - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); err = ipmi_request_settime(ipmi_device->user_interface, &tx_msg->addr, tx_msg->tx_msgid, @@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, status = AE_OK; end_label: - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_del(&tx_msg->head); - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); kfree(tx_msg); return status; } @@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) INIT_LIST_HEAD(&ipmi_device->head); - mutex_init(&ipmi_device->tx_msg_lock); + spin_lock_init(&ipmi_device->tx_msg_lock); INIT_LIST_HEAD(&ipmi_device->tx_msg_list); ipmi_install_space_handler(ipmi_device); -- cgit v1.2.3 From ea8117478918a4734586d35ff530721b682425be Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Sep 2013 12:43:13 +0200 Subject: sched, idle: Fix the idle polling state logic Mike reported that commit 7d1a9417 ("x86: Use generic idle loop") regressed several workloads and caused excessive reschedule interrupts. The patch in question failed to notice that the x86 code had an inverted sense of the polling state versus the new generic code (x86: default polling, generic: default !polling). Fix the two prominent x86 mwait based idle drivers and introduce a few new generic polling helpers (fixing the wrong smp_mb__after_clear_bit usage). Also switch the idle routines to using tif_need_resched() which is an immediate TIF_NEED_RESCHED test as opposed to need_resched which will end up being slightly different. Reported-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: lenb@kernel.org Cc: tglx@linutronix.de Link: http://lkml.kernel.org/n/tip-nc03imb0etuefmzybzj7sprf@git.kernel.org Signed-off-by: Ingo Molnar --- drivers/acpi/processor_idle.c | 46 ++++++++++--------------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f98dd00b51a9..c7414a545a4f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -119,17 +119,10 @@ static struct dmi_system_id processor_power_dmi_table[] = { */ static void acpi_safe_halt(void) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) { + if (!tif_need_resched()) { safe_halt(); local_irq_disable(); } - current_thread_info()->status |= TS_POLLING; } #ifdef ARCH_APICTIMER_STOPS_ON_C3 @@ -737,6 +730,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) + return -EINVAL; + } + lapic_timer_state_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); @@ -790,18 +788,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } /* @@ -819,9 +808,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } @@ -858,18 +844,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, } } - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } acpi_unlazy_tlb(smp_processor_id()); @@ -915,9 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } -- cgit v1.2.3 From bee7f9c83e1d18af6fee06b97b6558cbd1cded45 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Sep 2013 19:08:00 -0700 Subject: ACPI / x86: Increase override tables number limit Current ACPI tables in initrd is limited to 10, that is too small. 64 should be good enough as we have 35 sigs and could have several SSDT. Two problems in current code prevent us from increasing limit: 1. The cpio file info array is put in stack, as every element is 32 bytes, could run out of stack if we have that array size to 64. We can move it out from stack, make it global and put it into the __initdata section. 2. early_ioremap() only can remap 256k one time. Current code maps 10 tables at a time. If we increased that limit, the whole size could be more than 256k, so early_ioremap() would fail with that. We can map chunks one by one during copying, instead of mapping all of them together. Signed-off-by: Yinghai Acked-by: Tejun Heo Tested-by: Thomas Renninger Reviewed-by: Tang Chen Tested-by: Tang Chen Acked-by: Toshi Kani Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c7f66e..88bb9d05b038 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -569,8 +569,10 @@ static const char * const table_sigs[] = { #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) -/* Must not increase 10 or needs code modification below */ -#define ACPI_OVERRIDE_TABLES 10 +#define ACPI_OVERRIDE_TABLES 64 +static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; + +#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) void __init acpi_initrd_override(void *data, size_t size) { @@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size) struct acpi_table_header *table; char cpio_path[32] = "kernel/firmware/acpi/"; struct cpio_data file; - struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES]; - char *p; if (data == NULL || size == 0) return; @@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size) table->signature, cpio_path, file.name, table->length); all_tables_size += table->length; - early_initrd_files[table_nr].data = file.data; - early_initrd_files[table_nr].size = file.size; + acpi_initrd_files[table_nr].data = file.data; + acpi_initrd_files[table_nr].size = file.size; table_nr++; } if (table_nr == 0) @@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size) memblock_reserve(acpi_tables_addr, all_tables_size); arch_reserve_mem_area(acpi_tables_addr, all_tables_size); - p = early_ioremap(acpi_tables_addr, all_tables_size); - + /* + * early_ioremap only can remap 256k one time. If we map all + * tables one time, we will hit the limit. Need to map chunks + * one by one during copying the same as that in relocate_initrd(). + */ for (no = 0; no < table_nr; no++) { - memcpy(p + total_offset, early_initrd_files[no].data, - early_initrd_files[no].size); - total_offset += early_initrd_files[no].size; + unsigned char *src_p = acpi_initrd_files[no].data; + phys_addr_t size = acpi_initrd_files[no].size; + phys_addr_t dest_addr = acpi_tables_addr + total_offset; + phys_addr_t slop, clen; + char *dest_p; + + total_offset += size; + + while (size) { + slop = dest_addr & ~PAGE_MASK; + clen = size; + if (clen > MAP_CHUNK_SIZE - slop) + clen = MAP_CHUNK_SIZE - slop; + dest_p = early_ioremap(dest_addr & PAGE_MASK, + clen + slop); + memcpy(dest_p + slop, src_p, clen); + early_iounmap(dest_p, clen + slop); + src_p += clen; + dest_addr += clen; + size -= clen; + } } - early_iounmap(p, all_tables_size); } #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ -- cgit v1.2.3 From 302822996fd572676bb66a7c4351f6faa0e4ddfd Mon Sep 17 00:00:00 2001 From: Liu Chuansheng Date: Thu, 12 Sep 2013 01:42:57 +0800 Subject: ACPI / osl: implement acpi_os_sleep() with msleep() Currently, acpi_os_sleep() uses schedule_timeout_interruptible() which can be interrupted by a signal, and that causes the real sleep time to be shorter. According to the ACPI spec: The Sleep term is used to implement long-term timing requirements. Execution is delayed for at least the required number of milliseconds. The sleeping time should be at least the required number msecs, so use msleep() which guarantees that to implement it. Signed-off-by: Liu Chuansheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c7f66e..b1629b571cb2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -820,7 +820,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) void acpi_os_sleep(u64 ms) { - schedule_timeout_interruptible(msecs_to_jiffies(ms)); + msleep(ms); } void acpi_os_stall(u32 us) -- cgit v1.2.3 From 763f527b68c6b026439f0b12ebe232d96b5563df Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:03 -0400 Subject: ACPI / button: Using input_set_capability() to mark device's event capability Input layer provides input_set_capability() to set input device's event related bits. This patch is to use it to replace origin code. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index a55773801c5f..c971929d75c2 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device) switch (button->type) { case ACPI_BUTTON_TYPE_POWER: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_POWER, input->keybit); + input_set_capability(input, EV_KEY, KEY_POWER); break; case ACPI_BUTTON_TYPE_SLEEP: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_SLEEP, input->keybit); + input_set_capability(input, EV_KEY, KEY_SLEEP); break; case ACPI_BUTTON_TYPE_LID: - input->evbit[0] = BIT_MASK(EV_SW); - set_bit(SW_LID, input->swbit); + input_set_capability(input, EV_SW, SW_LID); break; } -- cgit v1.2.3 From 16a26e85279fd672050ffc3637038366629e8653 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:04 -0400 Subject: ACPI / EC: Convert all printk() calls to dynamic debug function This patch is to convert all printks in the ec driver to pr_debug/info/err and define pr_fmt macro to replace PREFIX. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a06d98374705..d5309fd49458 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -28,6 +28,7 @@ /* Uncomment next line to get verbose printout */ /* #define DEBUG */ +#define pr_fmt(fmt) "ACPI : EC: " fmt #include #include @@ -49,9 +50,6 @@ #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" -#undef PREFIX -#define PREFIX "ACPI: EC: " - /* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ @@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { u8 x = inb(ec->command_addr); - pr_debug(PREFIX "---> status = 0x%2.2x\n", x); + pr_debug("---> status = 0x%2.2x\n", x); return x; } static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { u8 x = inb(ec->data_addr); - pr_debug(PREFIX "---> data = 0x%2.2x\n", x); + pr_debug("---> data = 0x%2.2x\n", x); return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { - pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); + pr_debug("<--- command = 0x%2.2x\n", command); outb(command, ec->command_addr); } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { - pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); + pr_debug("<--- data = 0x%2.2x\n", data); outb(data, ec->data_addr); } @@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec) } advance_transaction(ec, acpi_ec_read_status(ec)); } while (time_before(jiffies, delay)); - pr_debug(PREFIX "controller reset, restart transaction\n"); + pr_debug("controller reset, restart transaction\n"); spin_lock_irqsave(&ec->lock, flags); start_transaction(ec); spin_unlock_irqrestore(&ec->lock, flags); @@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) } } if (ec_wait_ibf0(ec)) { - pr_err(PREFIX "input buffer is not empty, " + pr_err("input buffer is not empty, " "aborting transaction\n"); status = -ETIME; goto end; } - pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n", + pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", t->command, t->wdata ? t->wdata[0] : 0); /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { @@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ec_storm_threshold) { - pr_info(PREFIX "GPE storm detected(%d GPEs), " + pr_info("GPE storm detected(%d GPEs), " "transactions will use polling mode\n", t->irq_count); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } - pr_debug(PREFIX "transaction end\n"); + pr_debug("transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt) struct acpi_ec_query_handler *handler = cxt; if (!handler) return; - pr_debug(PREFIX "start query execution\n"); + pr_debug("start query execution\n"); if (handler->func) handler->func(handler->data); else if (handler->handle) acpi_evaluate_object(handler->handle, NULL, NULL, NULL); - pr_debug(PREFIX "stop query execution\n"); + pr_debug("stop query execution\n"); kfree(handler); } @@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) if (!copy) return -ENOMEM; memcpy(copy, handler, sizeof(*copy)); - pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + pr_debug("push query execution (0x%2x) on queue\n", + value); return acpi_os_execute((copy->func) ? OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, copy); @@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { - pr_debug(PREFIX "push gpe query to the queue\n"); + pr_debug("push gpe query to the queue\n"); return acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ec_gpe_query, ec); } @@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, struct acpi_ec *ec = data; u8 status = acpi_ec_read_status(ec); - pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status); + pr_debug("~~~> interrupt, status:0x%02x\n", status); advance_transaction(ec, status); if (ec_transaction_done(ec) && @@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec) * The AE_NOT_FOUND error will be ignored and OS * continue to initialize EC. */ - printk(KERN_ERR "Fail in evaluating the _REG object" + pr_err("Fail in evaluating the _REG object" " of EC device. Broken bios is suspected.\n"); } else { acpi_remove_gpe_handler(NULL, ec->gpe, @@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) acpi_disable_gpe(NULL, ec->gpe); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - pr_err(PREFIX "failed to remove space handler\n"); + pr_err("failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) - pr_err(PREFIX "failed to remove gpe handler\n"); + pr_err("failed to remove gpe handler\n"); clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); } @@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device) ret = !!request_region(ec->command_addr, 1, "EC cmd"); WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); - pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", + pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); ret = ec_install_handlers(ec); @@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { - printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); + pr_debug("Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void) status = acpi_get_table(ACPI_SIG_ECDT, 1, (struct acpi_table_header **)&ecdt_ptr); if (ACPI_SUCCESS(status)) { - pr_info(PREFIX "EC description table is found, configuring boot EC\n"); + pr_info("EC description table is found, configuring boot EC\n"); boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; @@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void) /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ - printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); + pr_debug("Look up EC in DSDT\n"); status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, boot_ec, NULL); /* Check that acpi_get_devices actually find something */ @@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void) saved_ec->data_addr != boot_ec->data_addr || saved_ec->gpe != boot_ec->gpe || saved_ec->handle != boot_ec->handle) - pr_info(PREFIX "ASUSTek keeps feeding us with broken " + pr_info("ASUSTek keeps feeding us with broken " "ECDT tables, which are very hard to workaround. " "Trying to use DSDT EC info instead. Please send " "output of acpidump to linux-acpi@vger.kernel.org\n"); -- cgit v1.2.3 From c48b156517348a0130e9e6edbeba95f9b4e50d65 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:05 -0400 Subject: ACPI / sysfs: make GPE sysfs attributes only accept correct values According to the design, GPE sysfs attributes should accept "disable", "enable", "clear" and integer numbers as params. Current code checks "disable", "enable" and "clear" first. If the param doesn't match, pass it to strtoul() as a string representing an integer number and assign the return value to the given GPE count. It is missing the check of whether or not the param really represents an integer number and strtoul() will return 0 if the string is not a number. This causes any params except for "enable", "disable", "clear" and a number to make the GPE count become 0. This patch is to use kstrtoul() to replace strtoul() and check the return value. If the convertion is successful, use as the new GPE count. If not, return an error. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 05306a59aedc..b55778704444 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj, acpi_event_status status; acpi_handle handle; int result = 0; + unsigned long tmp; if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { int i; @@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj, else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index); + else if (!kstrtoul(buf, 0, &tmp)) + all_counters[index].count = tmp; else - all_counters[index].count = strtoul(buf, NULL, 0); + result = -EINVAL; } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { int event = index - num_gpes; if (!strcmp(buf, "disable\n") && @@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj, else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_event(event); + else if (!kstrtoul(buf, 0, &tmp)) + all_counters[index].count = tmp; else - all_counters[index].count = strtoul(buf, NULL, 0); + result = -EINVAL; } else all_counters[index].count = strtoul(buf, NULL, 0); -- cgit v1.2.3 From cc8ef52707341e67a12067d6ead991d56ea017ca Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:45 +0800 Subject: ACPI / AC: convert ACPI ac driver to platform bus Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 163 +++++++++++++++++++++---------------------- drivers/acpi/acpi_platform.c | 1 + 2 files changed, 81 insertions(+), 83 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index f37beaa32750..324b5a096eff 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -34,6 +34,7 @@ #include #include #endif +#include #include #include #include @@ -61,39 +62,12 @@ extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); static int acpi_ac_open_fs(struct inode *inode, struct file *file); #endif -static int acpi_ac_add(struct acpi_device *device); -static int acpi_ac_remove(struct acpi_device *device); -static void acpi_ac_notify(struct acpi_device *device, u32 event); - -static const struct acpi_device_id ac_device_ids[] = { - {"ACPI0003", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, ac_device_ids); - -#ifdef CONFIG_PM_SLEEP -static int acpi_ac_resume(struct device *dev); -#endif -static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); - static int ac_sleep_before_get_state_ms; -static struct acpi_driver acpi_ac_driver = { - .name = "ac", - .class = ACPI_AC_CLASS, - .ids = ac_device_ids, - .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, - .ops = { - .add = acpi_ac_add, - .remove = acpi_ac_remove, - .notify = acpi_ac_notify, - }, - .drv.pm = &acpi_ac_pm, -}; - struct acpi_ac { struct power_supply charger; - struct acpi_device * device; + struct acpi_device *adev; + struct platform_device *pdev; unsigned long long state; }; @@ -115,15 +89,13 @@ static const struct file_operations acpi_ac_fops = { static int acpi_ac_get_state(struct acpi_ac *ac) { - acpi_status status = AE_OK; - + acpi_status status; - if (!ac) - return -EINVAL; - - status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); + status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL, + &ac->state); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); + ACPI_EXCEPTION((AE_INFO, status, + "Error reading AC Adapter state")); ac->state = ACPI_AC_STATUS_UNKNOWN; return -ENODEV; } @@ -201,36 +173,36 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); } -static int acpi_ac_add_fs(struct acpi_device *device) +static int acpi_ac_add_fs(struct acpi_ac *ac) { struct proc_dir_entry *entry = NULL; printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_ac_dir); - if (!acpi_device_dir(device)) + if (!acpi_device_dir(ac->adev)) { + acpi_device_dir(ac->adev) = + proc_mkdir(acpi_device_bid(ac->adev), acpi_ac_dir); + if (!acpi_device_dir(ac->adev)) return -ENODEV; } /* 'state' [R] */ entry = proc_create_data(ACPI_AC_FILE_STATE, - S_IRUGO, acpi_device_dir(device), - &acpi_ac_fops, acpi_driver_data(device)); + S_IRUGO, acpi_device_dir(ac->adev), + &acpi_ac_fops, ac); if (!entry) return -ENODEV; return 0; } -static int acpi_ac_remove_fs(struct acpi_device *device) +static int acpi_ac_remove_fs(struct acpi_ac *ac) { - if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); - - remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); - acpi_device_dir(device) = NULL; + if (acpi_device_dir(ac->adev)) { + remove_proc_entry(ACPI_AC_FILE_STATE, + acpi_device_dir(ac->adev)); + remove_proc_entry(acpi_device_bid(ac->adev), acpi_ac_dir); + acpi_device_dir(ac->adev) = NULL; } return 0; @@ -241,10 +213,9 @@ static int acpi_ac_remove_fs(struct acpi_device *device) Driver Model -------------------------------------------------------------------------- */ -static void acpi_ac_notify(struct acpi_device *device, u32 event) +static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) { - struct acpi_ac *ac = acpi_driver_data(device); - + struct acpi_ac *ac = data; if (!ac) return; @@ -267,10 +238,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, - (u32) ac->state); - acpi_notifier_call_chain(device, event, (u32) ac->state); + acpi_bus_generate_netlink_event(ac->adev->pnp.device_class, + dev_name(&ac->pdev->dev), + event, (u32) ac->state); + acpi_notifier_call_chain(ac->adev, event, (u32) ac->state); kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); } @@ -295,50 +266,61 @@ static struct dmi_system_id ac_dmi_table[] = { {}, }; -static int acpi_ac_add(struct acpi_device *device) +static int acpi_ac_probe(struct platform_device *pdev) { int result = 0; struct acpi_ac *ac = NULL; + struct acpi_device *adev; - - if (!device) + if (!pdev) return -EINVAL; + result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); + if (result) + return -ENODEV; + ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); if (!ac) return -ENOMEM; - ac->device = device; - strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_AC_CLASS); - device->driver_data = ac; + strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); + strcpy(acpi_device_class(adev), ACPI_AC_CLASS); + ac->adev = adev; + ac->pdev = pdev; + platform_set_drvdata(pdev, ac); result = acpi_ac_get_state(ac); if (result) goto end; #ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_ac_add_fs(device); -#endif + result = acpi_ac_add_fs(ac); if (result) goto end; - ac->charger.name = acpi_device_bid(device); +#endif + ac->charger.name = acpi_device_bid(adev); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; - result = power_supply_register(&ac->device->dev, &ac->charger); + result = power_supply_register(&pdev->dev, &ac->charger); if (result) goto end; + result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev), + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac); + if (result) { + power_supply_unregister(&ac->charger); + goto end; + } printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(device), acpi_device_bid(device), + acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); end: if (result) { #ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(device); + acpi_ac_remove_fs(ac); #endif kfree(ac); } @@ -356,7 +338,7 @@ static int acpi_ac_resume(struct device *dev) if (!dev) return -EINVAL; - ac = acpi_driver_data(to_acpi_device(dev)); + ac = platform_get_drvdata(to_platform_device(dev)); if (!ac) return -EINVAL; @@ -368,21 +350,24 @@ static int acpi_ac_resume(struct device *dev) return 0; } #endif +static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume); -static int acpi_ac_remove(struct acpi_device *device) +static int acpi_ac_remove(struct platform_device *pdev) { - struct acpi_ac *ac = NULL; - + struct acpi_ac *ac; - if (!device || !acpi_driver_data(device)) + if (!pdev) return -EINVAL; - ac = acpi_driver_data(device); + acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler); + ac = platform_get_drvdata(pdev); if (ac->charger.dev) power_supply_unregister(&ac->charger); + #ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(device); + acpi_ac_remove_fs(ac); #endif kfree(ac); @@ -390,6 +375,23 @@ static int acpi_ac_remove(struct acpi_device *device) return 0; } +static const struct acpi_device_id acpi_ac_match[] = { + { "ACPI0003", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, acpi_ac_match); + +static struct platform_driver acpi_ac_driver = { + .probe = acpi_ac_probe, + .remove = acpi_ac_remove, + .driver = { + .name = "acpi-ac", + .owner = THIS_MODULE, + .pm = &acpi_ac_pm_ops, + .acpi_match_table = ACPI_PTR(acpi_ac_match), + }, +}; + static int __init acpi_ac_init(void) { int result; @@ -403,7 +405,7 @@ static int __init acpi_ac_init(void) return -ENODEV; #endif - result = acpi_bus_register_driver(&acpi_ac_driver); + result = platform_driver_register(&acpi_ac_driver); if (result < 0) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); @@ -416,15 +418,10 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { - - acpi_bus_unregister_driver(&acpi_ac_driver); - + platform_driver_unregister(&acpi_ac_driver); #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); #endif - - return; } - module_init(acpi_ac_init); module_exit(acpi_ac_exit); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1bde12708f9e..6259bc28ef18 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -29,6 +29,7 @@ ACPI_MODULE_NAME("platform"); static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, + { "ACPI0003" }, { } }; -- cgit v1.2.3 From b5c37b798f2d29b9b2926e0abf008a13ce6c91fe Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:50 +0800 Subject: ideapad_laptop: convert ideapad device/driver to platform bus This patch does two things, 1. enumerate the ideapad device node to platform bus. 2. convert the current driver from ACPI bus to platform bus. Note, with this patch, the platform device node created by ACPI, with the name VPC2004:00, is used as the parent device of the input, backlight, rfkill sysfs class device. Plus the ideapad_platform private sysfs attributes, i.e. camera_power and fan_mode, are also moved to the new platform device node. The previous platform device node "ideapad" is removed. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 6259bc28ef18..c20b02beec7c 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -30,7 +30,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, { "ACPI0003" }, - + { "VPC2004" }, { } }; -- cgit v1.2.3 From b27b14cebfdb687e6d281d2cf82858a30796dc2a Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sun, 22 Sep 2013 15:42:41 +0800 Subject: ACPI / scan: fix typo in comments of acpi_bus_unregister_driver() "APIC" should be "ACPI" here. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fbdb82e70d10..611ce9061dc5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver) EXPORT_SYMBOL(acpi_bus_register_driver); /** - * acpi_bus_unregister_driver - unregisters a driver with the APIC bus + * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus * @driver: driver to unregister * * Unregisters a driver with the ACPI bus. Searches the namespace for all -- cgit v1.2.3 From e994d713a73716b54085a092b267099e40aa5513 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 25 Sep 2013 09:29:50 -0700 Subject: ACPI/thermal : Remove zone disabled warning Once thermal zone is disabled to move thermal control to user space, too many warnings printed in logs. Remove pr_warn from this path, instead warn when user mode issues request to disable thermal zone. Signed-off-by: Srinivas Pandruvada Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/acpi/thermal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 6a0329340b42..92bebb9d9438 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -515,10 +515,9 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; - if (!tz->tz_enabled) { - pr_warn("thermal zone is disabled \n"); + if (!tz->tz_enabled) return; - } + thermal_zone_device_update(tz->thermal_zone); } @@ -570,9 +569,10 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, */ if (mode == THERMAL_DEVICE_ENABLED) enable = 1; - else if (mode == THERMAL_DEVICE_DISABLED) + else if (mode == THERMAL_DEVICE_DISABLED) { enable = 0; - else + pr_warn("thermal zone will be disabled\n"); + } else return -EINVAL; if (enable != tz->tz_enabled) { -- cgit v1.2.3 From 6b68f03f95e3f0aeea0c47799aecb296276a7cd6 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:30 +0800 Subject: ACPI / IPMI: Fix potential response buffer overflow This patch enhances sanity checks on message size to avoid potential buffer overflow. The kernel IPMI message size is IPMI_MAX_MSG_LENGTH(272 bytes) while the ACPI specification defined IPMI message size is 64 bytes. The difference is not handled by the original codes. This may cause crash in the response handling codes. This patch closes this gap and also combines rx_data/tx_data to use single data/len pair since they need not be seperate. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 53 ++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index a6977e12d574..7397135702db 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -52,6 +52,7 @@ MODULE_LICENSE("GPL"); #define ACPI_IPMI_UNKNOWN 0x07 /* the IPMI timeout is 5s */ #define IPMI_TIMEOUT (5 * HZ) +#define ACPI_IPMI_MAX_MSG_LENGTH 64 struct acpi_ipmi_device { /* the device list attached to driver_data.ipmi_devices */ @@ -90,11 +91,9 @@ struct acpi_ipmi_msg { struct completion tx_complete; struct kernel_ipmi_msg tx_message; int msg_done; - /* tx data . And copy it from ACPI object buffer */ - u8 tx_data[64]; - int tx_len; - u8 rx_data[64]; - int rx_len; + /* tx/rx data . And copy it from/to ACPI object buffer */ + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; + u8 rx_len; struct acpi_ipmi_device *device; }; @@ -102,7 +101,7 @@ struct acpi_ipmi_msg { struct acpi_ipmi_buffer { u8 status; u8 length; - u8 data[64]; + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; }; static void ipmi_register_bmc(int iface, struct device *dev); @@ -141,7 +140,7 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) #define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) #define IPMI_OP_RGN_CMD(offset) (offset & 0xff) -static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, +static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, acpi_physical_address address, acpi_integer *value) { @@ -157,15 +156,21 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, */ msg->netfn = IPMI_OP_RGN_NETFN(address); msg->cmd = IPMI_OP_RGN_CMD(address); - msg->data = tx_msg->tx_data; + msg->data = tx_msg->data; /* * value is the parameter passed by the IPMI opregion space handler. * It points to the IPMI request message buffer */ buffer = (struct acpi_ipmi_buffer *)value; /* copy the tx message data */ + if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { + dev_WARN_ONCE(&tx_msg->device->pnp_dev->dev, true, + "Unexpected request (msg len %d).\n", + buffer->length); + return -EINVAL; + } msg->data_len = buffer->length; - memcpy(tx_msg->tx_data, buffer->data, msg->data_len); + memcpy(tx_msg->data, buffer->data, msg->data_len); /* * now the default type is SYSTEM_INTERFACE and channel type is BMC. * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE, @@ -183,6 +188,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; spin_unlock_irqrestore(&device->tx_msg_lock, flags); + return 0; } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, @@ -214,7 +220,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, */ buffer->status = ACPI_IPMI_OK; buffer->length = msg->rx_len; - memcpy(buffer->data, msg->rx_data, msg->rx_len); + memcpy(buffer->data, msg->data, msg->rx_len); } static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) @@ -250,8 +256,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) dev_warn(&pnp_dev->dev, "Unexpected response is returned. " "returned user %p, expected user %p\n", msg->user, ipmi_device->user_interface); - ipmi_free_recv_msg(msg); - return; + goto out_msg; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { @@ -265,17 +270,21 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - ipmi_free_recv_msg(msg); - return; + goto out_msg; } - if (msg->msg.data_len) { - /* copy the response data to Rx_data buffer */ - memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len); + /* copy the response data to Rx_data buffer */ + if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) { + dev_WARN_ONCE(&pnp_dev->dev, true, + "Unexpected response (msg len %d).\n", + msg->msg.data_len); + } else { tx_msg->rx_len = msg->msg.data_len; + memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); tx_msg->msg_done = 1; } complete(&tx_msg->tx_complete); +out_msg: ipmi_free_recv_msg(msg); }; @@ -398,7 +407,10 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if (!tx_msg) return AE_NO_MEMORY; - acpi_format_ipmi_msg(tx_msg, address, value); + if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { + status = AE_TYPE; + goto out_msg; + } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); @@ -409,17 +421,18 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, NULL, 0, 0, 0); if (err) { status = AE_ERROR; - goto end_label; + goto out_list; } rem_time = wait_for_completion_timeout(&tx_msg->tx_complete, IPMI_TIMEOUT); acpi_format_ipmi_response(tx_msg, value, rem_time); status = AE_OK; -end_label: +out_list: spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_del(&tx_msg->head); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); +out_msg: kfree(tx_msg); return status; } -- cgit v1.2.3 From 5ac557ef4951ea4b131ae45b08434546cb386ac5 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:39 +0800 Subject: ACPI / IPMI: Fix race caused by the unprotected ACPI IPMI transfers This patch fixes races caused by unprotected ACPI IPMI transfers. We can see that the following crashes may occur: 1. There is no tx_msg_lock held for iterating tx_msg_list in ipmi_flush_tx_msg() while it may be unlinked on failure in parallel in acpi_ipmi_space_handler() under tx_msg_lock. 2. There is no lock held for freeing tx_msg in acpi_ipmi_space_handler() while it may be accessed in parallel in ipmi_flush_tx_msg() and ipmi_msg_handler(). This patch enhances tx_msg_lock to protect all tx_msg accesses to solve this issue. Then tx_msg_lock is always held around complete() and tx_msg accesses. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 7397135702db..87307baeafab 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -228,11 +228,14 @@ static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) struct acpi_ipmi_msg *tx_msg, *temp; int count = HZ / 10; struct pnp_dev *pnp_dev = ipmi->pnp_dev; + unsigned long flags; + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); } + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); /* wait for about 100ms to flush the tx message list */ while (count--) { @@ -266,11 +269,10 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } } - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - goto out_msg; + goto out_lock; } /* copy the response data to Rx_data buffer */ @@ -284,6 +286,8 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) tx_msg->msg_done = 1; } complete(&tx_msg->tx_complete); +out_lock: + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: ipmi_free_recv_msg(msg); }; -- cgit v1.2.3 From 8584ec6ae9cc386de344e0d33b60f76368bb73ab Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:47 +0800 Subject: ACPI / IPMI: Fix race caused by the timed out ACPI IPMI transfers This patch fixes races caused by timed out ACPI IPMI transfers. This patch uses timeout mechanism provided by ipmi_si to avoid the race that the msg_done flag is set but without any protection, its content can be invalid. Thanks for the suggestion of Corey Minyard. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 49 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 87307baeafab..9171a1a668f2 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -51,7 +51,7 @@ MODULE_LICENSE("GPL"); #define ACPI_IPMI_TIMEOUT 0x10 #define ACPI_IPMI_UNKNOWN 0x07 /* the IPMI timeout is 5s */ -#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_TIMEOUT (5000) #define ACPI_IPMI_MAX_MSG_LENGTH 64 struct acpi_ipmi_device { @@ -135,6 +135,7 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; + ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN; return ipmi_msg; } @@ -192,7 +193,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, - acpi_integer *value, int rem_time) + acpi_integer *value) { struct acpi_ipmi_buffer *buffer; @@ -201,24 +202,17 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, * IPMI message returned by IPMI command. */ buffer = (struct acpi_ipmi_buffer *)value; - if (!rem_time && !msg->msg_done) { - buffer->status = ACPI_IPMI_TIMEOUT; - return; - } /* - * If the flag of msg_done is not set or the recv length is zero, it - * means that the IPMI command is not executed correctly. - * The status code will be ACPI_IPMI_UNKNOWN. + * If the flag of msg_done is not set, it means that the IPMI command is + * not executed correctly. */ - if (!msg->msg_done || !msg->rx_len) { - buffer->status = ACPI_IPMI_UNKNOWN; + buffer->status = msg->msg_done; + if (msg->msg_done != ACPI_IPMI_OK) return; - } /* * If the IPMI response message is obtained correctly, the status code * will be ACPI_IPMI_OK */ - buffer->status = ACPI_IPMI_OK; buffer->length = msg->rx_len; memcpy(buffer->data, msg->data, msg->rx_len); } @@ -280,11 +274,23 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) dev_WARN_ONCE(&pnp_dev->dev, true, "Unexpected response (msg len %d).\n", msg->msg.data_len); - } else { - tx_msg->rx_len = msg->msg.data_len; - memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); - tx_msg->msg_done = 1; + goto out_comp; } + /* response msg is an error msg */ + msg->recv_type = IPMI_RESPONSE_RECV_TYPE; + if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && + msg->msg.data_len == 1) { + if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) { + dev_WARN_ONCE(&pnp_dev->dev, true, + "Unexpected response (timeout).\n"); + tx_msg->msg_done = ACPI_IPMI_TIMEOUT; + } + goto out_comp; + } + tx_msg->rx_len = msg->msg.data_len; + memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); + tx_msg->msg_done = ACPI_IPMI_OK; +out_comp: complete(&tx_msg->tx_complete); out_lock: spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); @@ -392,7 +398,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, { struct acpi_ipmi_msg *tx_msg; struct acpi_ipmi_device *ipmi_device = handler_context; - int err, rem_time; + int err; acpi_status status; unsigned long flags; /* @@ -422,14 +428,13 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, &tx_msg->addr, tx_msg->tx_msgid, &tx_msg->tx_message, - NULL, 0, 0, 0); + NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; goto out_list; } - rem_time = wait_for_completion_timeout(&tx_msg->tx_complete, - IPMI_TIMEOUT); - acpi_format_ipmi_response(tx_msg, value, rem_time); + wait_for_completion(&tx_msg->tx_complete); + acpi_format_ipmi_response(tx_msg, value); status = AE_OK; out_list: -- cgit v1.2.3 From a1a69b297e4775298d6407357332ea1adc218396 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:54 +0800 Subject: ACPI / IPMI: Fix race caused by the unprotected ACPI IPMI user This patch uses reference counting to fix the race caused by the unprotected ACPI IPMI user. There are two rules for using the ipmi_si APIs: 1. In ipmi_si, ipmi_destroy_user() can ensure that no ipmi_recv_msg will be passed to ipmi_msg_handler(), but ipmi_request_settime() can not use an invalid ipmi_user_t. This means the ipmi_si users must ensure that there won't be any local references on ipmi_user_t before invoking ipmi_destroy_user(). 2. In ipmi_si, the smi_gone()/new_smi() callbacks are protected by smi_watchers_mutex, so their execution is serialized. But as a new smi can re-use a freed intf_num, it requires that the callback implementation must not use intf_num as an identification mean or it must ensure all references to the previous smi are all dropped before exiting smi_gone() callback. As the acpi_ipmi_device->user_interface check in acpi_ipmi_space_handler() can happen before setting user_interface to NULL and codes after the check in acpi_ipmi_space_handler() can happen after user_interface becomes NULL, the on-going acpi_ipmi_space_handler() still can pass an invalid acpi_ipmi_device->user_interface to ipmi_request_settime(). Such race conditions are not allowed by the IPMI layer's API design as a crash will happen in ipmi_request_settime() if something like that happens. This patch follows the ipmi_devintf.c design: 1. Invoke ipmi_destroy_user() after the reference count of acpi_ipmi_device drops to 0. References of acpi_ipmi_device dropping to 0 also means tx_msg related to this acpi_ipmi_device are all freed. This matches the IPMI layer's API calling rule on ipmi_destroy_user() and ipmi_request_settime(). 2. ipmi_flush_tx_msg() is performed so that no on-going tx_msg can still be running in acpi_ipmi_space_handler(). And it is invoked after invoking __ipmi_dev_kill() where acpi_ipmi_device is deleted from the list with a "dead" flag set, and the "dead" flag check is also introduced to the point where a tx_msg is going to be added to the tx_msg_list so that no new tx_msg can be created after returning from the __ipmi_dev_kill(). 3. The waiting codes in ipmi_flush_tx_msg() is deleted because it is not required since this patch ensures no acpi_ipmi reference is still held for ipmi_user_t before calling ipmi_destroy_user() and ipmi_destroy_user() can ensure no more ipmi_msg_handler() can happen after returning from ipmi_destroy_user(). 4. The flushing of tx_msg is also moved out of ipmi_lock in this patch. The forthcoming IPMI operation region handler installation changes also requires acpi_ipmi_device be handled in this style. The header comment of the file is also updated due to this design change. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 249 +++++++++++++++++++++++++++++------------------ 1 file changed, 156 insertions(+), 93 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 9171a1a668f2..b285386eb37f 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -1,8 +1,9 @@ /* * acpi_ipmi.c - ACPI IPMI opregion * - * Copyright (C) 2010 Intel Corporation - * Copyright (C) 2010 Zhao Yakui + * Copyright (C) 2010, 2013 Intel Corporation + * Author: Zhao Yakui + * Lv Zheng * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -67,6 +68,8 @@ struct acpi_ipmi_device { long curr_msgid; unsigned long flags; struct ipmi_smi_info smi_data; + bool dead; + struct kref kref; }; struct ipmi_driver_data { @@ -107,8 +110,8 @@ struct acpi_ipmi_buffer { static void ipmi_register_bmc(int iface, struct device *dev); static void ipmi_bmc_gone(int iface); static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); -static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device); -static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device); +static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi); +static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi); static struct ipmi_driver_data driver_data = { .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), @@ -122,6 +125,88 @@ static struct ipmi_driver_data driver_data = { }, }; +static struct acpi_ipmi_device * +ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) +{ + struct acpi_ipmi_device *ipmi_device; + int err; + ipmi_user_t user; + + ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL); + if (!ipmi_device) + return NULL; + + kref_init(&ipmi_device->kref); + INIT_LIST_HEAD(&ipmi_device->head); + INIT_LIST_HEAD(&ipmi_device->tx_msg_list); + spin_lock_init(&ipmi_device->tx_msg_lock); + + ipmi_device->handle = handle; + ipmi_device->pnp_dev = to_pnp_dev(get_device(smi_data->dev)); + memcpy(&ipmi_device->smi_data, smi_data, sizeof(struct ipmi_smi_info)); + ipmi_device->ipmi_ifnum = iface; + + err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, + ipmi_device, &user); + if (err) { + put_device(smi_data->dev); + kfree(ipmi_device); + return NULL; + } + ipmi_device->user_interface = user; + ipmi_install_space_handler(ipmi_device); + + return ipmi_device; +} + +static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) +{ + ipmi_remove_space_handler(ipmi_device); + ipmi_destroy_user(ipmi_device->user_interface); + put_device(ipmi_device->smi_data.dev); + kfree(ipmi_device); +} + +static void ipmi_dev_release_kref(struct kref *kref) +{ + struct acpi_ipmi_device *ipmi = + container_of(kref, struct acpi_ipmi_device, kref); + + ipmi_dev_release(ipmi); +} + +static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) +{ + list_del(&ipmi_device->head); + /* + * Always setting dead flag after deleting from the list or + * list_for_each_entry() codes must get changed. + */ + ipmi_device->dead = true; +} + +static struct acpi_ipmi_device *acpi_ipmi_dev_get(int iface) +{ + struct acpi_ipmi_device *temp, *ipmi_device = NULL; + + mutex_lock(&driver_data.ipmi_lock); + list_for_each_entry(temp, &driver_data.ipmi_devices, head) { + if (temp->ipmi_ifnum == iface) { + ipmi_device = temp; + kref_get(&ipmi_device->kref); + break; + } + } + mutex_unlock(&driver_data.ipmi_lock); + + return ipmi_device; +} + +static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device) +{ + kref_put(&ipmi_device->kref, ipmi_dev_release_kref); +} + static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) { struct acpi_ipmi_msg *ipmi_msg; @@ -220,25 +305,22 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) { struct acpi_ipmi_msg *tx_msg, *temp; - int count = HZ / 10; - struct pnp_dev *pnp_dev = ipmi->pnp_dev; unsigned long flags; + /* + * NOTE: On-going ipmi_recv_msg + * ipmi_msg_handler() may still be invoked by ipmi_si after + * flushing. But it is safe to do a fast flushing on module_exit() + * without waiting for all ipmi_recv_msg(s) to complete from + * ipmi_msg_handler() as it is ensured by ipmi_si that all + * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user(). + */ spin_lock_irqsave(&ipmi->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); } spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); - - /* wait for about 100ms to flush the tx message list */ - while (count--) { - if (list_empty(&ipmi->tx_msg_list)) - break; - schedule_timeout(1); - } - if (!list_empty(&ipmi->tx_msg_list)) - dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n"); } static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) @@ -302,7 +384,6 @@ static void ipmi_register_bmc(int iface, struct device *dev) { struct acpi_ipmi_device *ipmi_device, *temp; struct pnp_dev *pnp_dev; - ipmi_user_t user; int err; struct ipmi_smi_info smi_data; acpi_handle handle; @@ -312,12 +393,18 @@ static void ipmi_register_bmc(int iface, struct device *dev) if (err) return; - if (smi_data.addr_src != SI_ACPI) { - put_device(smi_data.dev); - return; - } - + if (smi_data.addr_src != SI_ACPI) + goto err_ref; handle = smi_data.addr_info.acpi_info.acpi_handle; + if (!handle) + goto err_ref; + pnp_dev = to_pnp_dev(smi_data.dev); + + ipmi_device = ipmi_dev_alloc(iface, &smi_data, handle); + if (!ipmi_device) { + dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); + goto err_ref; + } mutex_lock(&driver_data.ipmi_lock); list_for_each_entry(temp, &driver_data.ipmi_devices, head) { @@ -326,34 +413,18 @@ static void ipmi_register_bmc(int iface, struct device *dev) * to the device list, don't add it again. */ if (temp->handle == handle) - goto out; + goto err_lock; } - ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL); - - if (!ipmi_device) - goto out; - - pnp_dev = to_pnp_dev(smi_data.dev); - ipmi_device->handle = handle; - ipmi_device->pnp_dev = pnp_dev; - - err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, - ipmi_device, &user); - if (err) { - dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); - kfree(ipmi_device); - goto out; - } - acpi_add_ipmi_device(ipmi_device); - ipmi_device->user_interface = user; - ipmi_device->ipmi_ifnum = iface; + list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); - memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info)); + put_device(smi_data.dev); return; -out: +err_lock: mutex_unlock(&driver_data.ipmi_lock); + ipmi_dev_release(ipmi_device); +err_ref: put_device(smi_data.dev); return; } @@ -361,19 +432,22 @@ out: static void ipmi_bmc_gone(int iface) { struct acpi_ipmi_device *ipmi_device, *temp; + bool dev_found = false; mutex_lock(&driver_data.ipmi_lock); list_for_each_entry_safe(ipmi_device, temp, &driver_data.ipmi_devices, head) { - if (ipmi_device->ipmi_ifnum != iface) - continue; - - acpi_remove_ipmi_device(ipmi_device); - put_device(ipmi_device->smi_data.dev); - kfree(ipmi_device); - break; + if (ipmi_device->ipmi_ifnum != iface) { + dev_found = true; + __ipmi_dev_kill(ipmi_device); + break; + } } mutex_unlock(&driver_data.ipmi_lock); + if (dev_found) { + ipmi_flush_tx_msg(ipmi_device); + acpi_ipmi_dev_put(ipmi_device); + } } /* -------------------------------------------------------------------------- * Address Space Management @@ -397,7 +471,8 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; - struct acpi_ipmi_device *ipmi_device = handler_context; + int iface = (long)handler_context; + struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; unsigned long flags; @@ -410,20 +485,31 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - if (!ipmi_device->user_interface) + ipmi_device = acpi_ipmi_dev_get(iface); + if (!ipmi_device) return AE_NOT_EXIST; tx_msg = acpi_alloc_ipmi_msg(ipmi_device); - if (!tx_msg) - return AE_NO_MEMORY; + if (!tx_msg) { + status = AE_NO_MEMORY; + goto out_ref; + } if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { status = AE_TYPE; goto out_msg; } + mutex_lock(&driver_data.ipmi_lock); + /* Do not add a tx_msg that can not be flushed. */ + if (ipmi_device->dead) { + status = AE_NOT_EXIST; + mutex_unlock(&driver_data.ipmi_lock); + goto out_msg; + } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); + mutex_unlock(&driver_data.ipmi_lock); err = ipmi_request_settime(ipmi_device->user_interface, &tx_msg->addr, tx_msg->tx_msgid, @@ -443,6 +529,8 @@ out_list: spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: kfree(tx_msg); +out_ref: + acpi_ipmi_dev_put(ipmi_device); return status; } @@ -465,9 +553,8 @@ static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) return 0; status = acpi_install_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, - &acpi_ipmi_space_handler, - NULL, ipmi); + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, + NULL, (void *)((long)ipmi->ipmi_ifnum)); if (ACPI_FAILURE(status)) { struct pnp_dev *pnp_dev = ipmi->pnp_dev; dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space " @@ -478,36 +565,6 @@ static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) return 0; } -static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) -{ - - INIT_LIST_HEAD(&ipmi_device->head); - - spin_lock_init(&ipmi_device->tx_msg_lock); - INIT_LIST_HEAD(&ipmi_device->tx_msg_list); - ipmi_install_space_handler(ipmi_device); - - list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); -} - -static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device) -{ - /* - * If the IPMI user interface is created, it should be - * destroyed. - */ - if (ipmi_device->user_interface) { - ipmi_destroy_user(ipmi_device->user_interface); - ipmi_device->user_interface = NULL; - } - /* flush the Tx_msg list */ - if (!list_empty(&ipmi_device->tx_msg_list)) - ipmi_flush_tx_msg(ipmi_device); - - list_del(&ipmi_device->head); - ipmi_remove_space_handler(ipmi_device); -} - static int __init acpi_ipmi_init(void) { int result = 0; @@ -524,7 +581,7 @@ static int __init acpi_ipmi_init(void) static void __exit acpi_ipmi_exit(void) { - struct acpi_ipmi_device *ipmi_device, *temp; + struct acpi_ipmi_device *ipmi_device; if (acpi_disabled) return; @@ -538,11 +595,17 @@ static void __exit acpi_ipmi_exit(void) * handler and free it. */ mutex_lock(&driver_data.ipmi_lock); - list_for_each_entry_safe(ipmi_device, temp, - &driver_data.ipmi_devices, head) { - acpi_remove_ipmi_device(ipmi_device); - put_device(ipmi_device->smi_data.dev); - kfree(ipmi_device); + while (!list_empty(&driver_data.ipmi_devices)) { + ipmi_device = list_first_entry(&driver_data.ipmi_devices, + struct acpi_ipmi_device, + head); + __ipmi_dev_kill(ipmi_device); + mutex_unlock(&driver_data.ipmi_lock); + + ipmi_flush_tx_msg(ipmi_device); + acpi_ipmi_dev_put(ipmi_device); + + mutex_lock(&driver_data.ipmi_lock); } mutex_unlock(&driver_data.ipmi_lock); } -- cgit v1.2.3 From e96a94edd7ae302168e17daa0198b9ef08b2109d Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:02 +0800 Subject: ACPI / IPMI: Use global IPMI operation region handler It is found on a real machine, in its ACPI namespace, the IPMI OperationRegions (in the ACPI000D - ACPI power meter) are not defined under the IPMI system interface device (the IPI0001 with KCS type returned from _IFT control method): Device (PMI0) { Name (_HID, "ACPI000D") // _HID: Hardware ID OperationRegion (SYSI, IPMI, 0x0600, 0x0100) Field (SYSI, BufferAcc, Lock, Preserve) { AccessAs (BufferAcc, 0x01), Offset (0x58), SCMD, 8, GCMD, 8 } OperationRegion (POWR, IPMI, 0x3000, 0x0100) Field (POWR, BufferAcc, Lock, Preserve) { AccessAs (BufferAcc, 0x01), Offset (0xB3), GPMM, 8 } } Device (PCI0) { Device (ISA) { Device (NIPM) { Name (_HID, EisaId ("IPI0001")) // _HID: Hardware ID Method (_IFT, 0, NotSerialized) // _IFT: IPMI Interface Type { Return (0x01) } } } } Current ACPI_IPMI code registers IPMI operation region handler on a per-device basis, so for the above namespace the IPMI operation region handler is registered only under the scope of \_SB.PCI0.ISA.NIPM. Thus when an IPMI operation region field of \PMI0 is accessed, there are errors reported on such platform: ACPI Error: No handlers for Region [IPMI] ACPI Error: Region IPMI(7) has no handler The solution is to install an IPMI operation region handler from root node so that every object that defines IPMI OperationRegion can get an address space handler registered. When an IPMI operation region field is accessed, the Network Function (0x06 for SYSI and 0x30 for POWR) and the Command (SCMD, GCMD, GPMM) are passed to the operation region handler, there is no system interface specified by the BIOS. The patch tries to select one system interface by monitoring the system interface notification. IPMI messages passed from the ACPI codes are sent to this selected global IPMI system interface. The ACPI_IPMI will always select the first registered IPMI interface with an ACPI handle (i.e., defined in the ACPI namespace). It's hard to determine the selection when there are multiple IPMI system interfaces defined in the ACPI namespace. According to the IPMI specification: A BMC device may make available multiple system interfaces, but only one management controller is allowed to be 'active' BMC that provides BMC functionality for the system (in case of a 'partitioned' system, there can be only one active BMC per partition). Only the system interface(s) for the active BMC allowed to respond to the 'Get Device Id' command. According to the ipmi_si desigin: The ipmi_si registeration notifications can only happen after a successful "Get Device ID" command. Thus it should be OK for non-partitioned systems to do such selection. However, we do not have much knowledge on 'partitioned' systems. References: https://bugzilla.kernel.org/show_bug.cgi?id=46741 Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 81 ++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index b285386eb37f..7ec4cd1e7245 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -46,7 +46,6 @@ MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); MODULE_LICENSE("GPL"); -#define IPMI_FLAGS_HANDLER_INSTALL 0 #define ACPI_IPMI_OK 0 #define ACPI_IPMI_TIMEOUT 0x10 @@ -66,7 +65,6 @@ struct acpi_ipmi_device { ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; - unsigned long flags; struct ipmi_smi_info smi_data; bool dead; struct kref kref; @@ -77,6 +75,14 @@ struct ipmi_driver_data { struct ipmi_smi_watcher bmc_events; struct ipmi_user_hndl ipmi_hndlrs; struct mutex ipmi_lock; + /* + * NOTE: IPMI System Interface Selection + * There is no system interface specified by the IPMI operation + * region access. We try to select one system interface with ACPI + * handle set. IPMI messages passed from the ACPI codes are sent + * to this selected global IPMI system interface. + */ + struct acpi_ipmi_device *selected_smi; }; struct acpi_ipmi_msg { @@ -110,8 +116,6 @@ struct acpi_ipmi_buffer { static void ipmi_register_bmc(int iface, struct device *dev); static void ipmi_bmc_gone(int iface); static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); -static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi); -static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi); static struct ipmi_driver_data driver_data = { .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), @@ -154,14 +158,12 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) return NULL; } ipmi_device->user_interface = user; - ipmi_install_space_handler(ipmi_device); return ipmi_device; } static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) { - ipmi_remove_space_handler(ipmi_device); ipmi_destroy_user(ipmi_device->user_interface); put_device(ipmi_device->smi_data.dev); kfree(ipmi_device); @@ -178,6 +180,8 @@ static void ipmi_dev_release_kref(struct kref *kref) static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) { list_del(&ipmi_device->head); + if (driver_data.selected_smi == ipmi_device) + driver_data.selected_smi = NULL; /* * Always setting dead flag after deleting from the list or * list_for_each_entry() codes must get changed. @@ -185,17 +189,14 @@ static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) ipmi_device->dead = true; } -static struct acpi_ipmi_device *acpi_ipmi_dev_get(int iface) +static struct acpi_ipmi_device *acpi_ipmi_dev_get(void) { - struct acpi_ipmi_device *temp, *ipmi_device = NULL; + struct acpi_ipmi_device *ipmi_device = NULL; mutex_lock(&driver_data.ipmi_lock); - list_for_each_entry(temp, &driver_data.ipmi_devices, head) { - if (temp->ipmi_ifnum == iface) { - ipmi_device = temp; - kref_get(&ipmi_device->kref); - break; - } + if (driver_data.selected_smi) { + ipmi_device = driver_data.selected_smi; + kref_get(&ipmi_device->kref); } mutex_unlock(&driver_data.ipmi_lock); @@ -416,6 +417,8 @@ static void ipmi_register_bmc(int iface, struct device *dev) goto err_lock; } + if (!driver_data.selected_smi) + driver_data.selected_smi = ipmi_device; list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); put_device(smi_data.dev); @@ -443,6 +446,10 @@ static void ipmi_bmc_gone(int iface) break; } } + if (!driver_data.selected_smi) + driver_data.selected_smi = list_first_entry_or_null( + &driver_data.ipmi_devices, + struct acpi_ipmi_device, head); mutex_unlock(&driver_data.ipmi_lock); if (dev_found) { ipmi_flush_tx_msg(ipmi_device); @@ -471,7 +478,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; - int iface = (long)handler_context; struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; @@ -485,7 +491,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - ipmi_device = acpi_ipmi_dev_get(iface); + ipmi_device = acpi_ipmi_dev_get(); if (!ipmi_device) return AE_NOT_EXIST; @@ -534,47 +540,26 @@ out_ref: return status; } -static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi) -{ - if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) - return; - - acpi_remove_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); - - clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); -} - -static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) -{ - acpi_status status; - - if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) - return 0; - - status = acpi_install_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, - NULL, (void *)((long)ipmi->ipmi_ifnum)); - if (ACPI_FAILURE(status)) { - struct pnp_dev *pnp_dev = ipmi->pnp_dev; - dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space " - "handle\n"); - return -EINVAL; - } - set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); - return 0; -} - static int __init acpi_ipmi_init(void) { int result = 0; + acpi_status status; if (acpi_disabled) return result; mutex_init(&driver_data.ipmi_lock); + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_warn("Can't register IPMI opregion space handle\n"); + return -EINVAL; + } result = ipmi_smi_watcher_register(&driver_data.bmc_events); + if (result) + pr_err("Can't register IPMI system interface watcher\n"); return result; } @@ -608,6 +593,8 @@ static void __exit acpi_ipmi_exit(void) mutex_lock(&driver_data.ipmi_lock); } mutex_unlock(&driver_data.ipmi_lock); + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); } module_init(acpi_ipmi_init); -- cgit v1.2.3 From 7b9844772237e34968ffd4b086d7b5ed36b30856 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:11 +0800 Subject: ACPI / IPMI: Add reference counting for ACPI IPMI transfers This patch adds reference counting for ACPI IPMI transfers to tune the locking granularity of tx_msg_lock. This patch also makes the whole acpi_ipmi module's coding style consistent by using reference counting for all its objects (i.e., acpi_ipmi_device and acpi_ipmi_msg). The acpi_ipmi_msg handling is re-designed using referece counting. 1. tx_msg is always unlinked before complete(), so that it is safe to put complete() out side of tx_msg_lock. 2. tx_msg reference counters are incremented before calling ipmi_request_settime() and tx_msg_lock protection is added to ipmi_cancel_tx_msg() so that a complete() can be safely called in parellel with tx_msg unlinking in failure cases. 3. tx_msg holds a reference to acpi_ipmi_device so that it can be flushed and freed in the contexts other than acpi_ipmi_space_handler(). The lockdep_chains shows all acpi_ipmi locks are leaf locks after the tuning: 1. ipmi_lock is always leaf: irq_context: 0 [ffffffff81a943f8] smi_watchers_mutex [ffffffffa06eca60] driver_data.ipmi_lock irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a6678] s_active#103 [ffffffffa06eca60] driver_data.ipmi_lock 2. without this patch applied, lock used by complete() is held after holding tx_msg_lock: irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a6678] s_active#103 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 [ffffffff81e36620] &p->pi_lock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 [ffffffff81e36620] &p->pi_lock [ffffffff81e5d0a8] &rq->lock 3. with this patch applied, tx_msg_lock is always leaf: irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a66d8] s_active#107 [ffffffffa07ecdc8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa07ecdc8] &(&ipmi_device->tx_msg_lock)->rlock Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 117 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 32 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 7ec4cd1e7245..b9da5ef39024 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -104,6 +104,7 @@ struct acpi_ipmi_msg { u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; u8 rx_len; struct acpi_ipmi_device *device; + struct kref kref; }; /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */ @@ -208,16 +209,20 @@ static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device) kref_put(&ipmi_device->kref, ipmi_dev_release_kref); } -static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) +static struct acpi_ipmi_msg *ipmi_msg_alloc(void) { + struct acpi_ipmi_device *ipmi; struct acpi_ipmi_msg *ipmi_msg; - struct pnp_dev *pnp_dev = ipmi->pnp_dev; + ipmi = acpi_ipmi_dev_get(); + if (!ipmi) + return NULL; ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL); - if (!ipmi_msg) { - dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n"); + if (!ipmi_msg) { + acpi_ipmi_dev_put(ipmi); return NULL; } + kref_init(&ipmi_msg->kref); init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; @@ -225,6 +230,32 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) return ipmi_msg; } +static void ipmi_msg_release(struct acpi_ipmi_msg *tx_msg) +{ + acpi_ipmi_dev_put(tx_msg->device); + kfree(tx_msg); +} + +static void ipmi_msg_release_kref(struct kref *kref) +{ + struct acpi_ipmi_msg *tx_msg = + container_of(kref, struct acpi_ipmi_msg, kref); + + ipmi_msg_release(tx_msg); +} + +static struct acpi_ipmi_msg *acpi_ipmi_msg_get(struct acpi_ipmi_msg *tx_msg) +{ + kref_get(&tx_msg->kref); + + return tx_msg; +} + +static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg) +{ + kref_put(&tx_msg->kref, ipmi_msg_release_kref); +} + #define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) #define IPMI_OP_RGN_CMD(offset) (offset & 0xff) static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, @@ -305,7 +336,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) { - struct acpi_ipmi_msg *tx_msg, *temp; + struct acpi_ipmi_msg *tx_msg; unsigned long flags; /* @@ -317,18 +348,47 @@ static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user(). */ spin_lock_irqsave(&ipmi->tx_msg_lock, flags); - list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { + while (!list_empty(&ipmi->tx_msg_list)) { + tx_msg = list_first_entry(&ipmi->tx_msg_list, + struct acpi_ipmi_msg, + head); + list_del(&tx_msg->head); + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); + /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); + acpi_ipmi_msg_put(tx_msg); + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); + } + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); +} + +static void ipmi_cancel_tx_msg(struct acpi_ipmi_device *ipmi, + struct acpi_ipmi_msg *msg) +{ + struct acpi_ipmi_msg *tx_msg, *temp; + bool msg_found = false; + unsigned long flags; + + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); + list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { + if (msg == tx_msg) { + msg_found = true; + list_del(&tx_msg->head); + break; + } } spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); + + if (msg_found) + acpi_ipmi_msg_put(tx_msg); } static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) { struct acpi_ipmi_device *ipmi_device = user_msg_data; - int msg_found = 0; - struct acpi_ipmi_msg *tx_msg; + bool msg_found = false; + struct acpi_ipmi_msg *tx_msg, *temp; struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; unsigned long flags; @@ -339,17 +399,19 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) goto out_msg; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); - list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { + list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { - msg_found = 1; + msg_found = true; + list_del(&tx_msg->head); break; } } + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - goto out_lock; + goto out_msg; } /* copy the response data to Rx_data buffer */ @@ -375,8 +437,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) tx_msg->msg_done = ACPI_IPMI_OK; out_comp: complete(&tx_msg->tx_complete); -out_lock: - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); + acpi_ipmi_msg_put(tx_msg); out_msg: ipmi_free_recv_msg(msg); }; @@ -491,26 +552,23 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - ipmi_device = acpi_ipmi_dev_get(); - if (!ipmi_device) + tx_msg = ipmi_msg_alloc(); + if (!tx_msg) return AE_NOT_EXIST; - tx_msg = acpi_alloc_ipmi_msg(ipmi_device); - if (!tx_msg) { - status = AE_NO_MEMORY; - goto out_ref; - } + ipmi_device = tx_msg->device; if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { - status = AE_TYPE; - goto out_msg; + ipmi_msg_release(tx_msg); + return AE_TYPE; } + acpi_ipmi_msg_get(tx_msg); mutex_lock(&driver_data.ipmi_lock); /* Do not add a tx_msg that can not be flushed. */ if (ipmi_device->dead) { - status = AE_NOT_EXIST; mutex_unlock(&driver_data.ipmi_lock); - goto out_msg; + ipmi_msg_release(tx_msg); + return AE_NOT_EXIST; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); @@ -523,20 +581,15 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; - goto out_list; + goto out_msg; } wait_for_completion(&tx_msg->tx_complete); acpi_format_ipmi_response(tx_msg, value); status = AE_OK; -out_list: - spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); - list_del(&tx_msg->head); - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: - kfree(tx_msg); -out_ref: - acpi_ipmi_dev_put(ipmi_device); + ipmi_cancel_tx_msg(ipmi_device, tx_msg); + acpi_ipmi_msg_put(tx_msg); return status; } -- cgit v1.2.3 From 2fb037b89a3125627f02c40af3e3d38c3228184b Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:21 +0800 Subject: ACPI / IPMI: Cleanup several acpi_ipmi_device members This (trivial) patch: 1. Deletes a member of the acpi_ipmi_device, smi_data, which is not actually used. 2. Updates a member of the acpi_ipmi_device, pnp_dev, which is only used by dev_warn() invocations, so changes it to a struct device. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index b9da5ef39024..90d57c86db85 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -61,11 +61,10 @@ struct acpi_ipmi_device { struct list_head tx_msg_list; spinlock_t tx_msg_lock; acpi_handle handle; - struct pnp_dev *pnp_dev; + struct device *dev; ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; - struct ipmi_smi_info smi_data; bool dead; struct kref kref; }; @@ -131,7 +130,7 @@ static struct ipmi_driver_data driver_data = { }; static struct acpi_ipmi_device * -ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) +ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle) { struct acpi_ipmi_device *ipmi_device; int err; @@ -147,14 +146,13 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) spin_lock_init(&ipmi_device->tx_msg_lock); ipmi_device->handle = handle; - ipmi_device->pnp_dev = to_pnp_dev(get_device(smi_data->dev)); - memcpy(&ipmi_device->smi_data, smi_data, sizeof(struct ipmi_smi_info)); + ipmi_device->dev = get_device(dev); ipmi_device->ipmi_ifnum = iface; err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, ipmi_device, &user); if (err) { - put_device(smi_data->dev); + put_device(dev); kfree(ipmi_device); return NULL; } @@ -166,7 +164,7 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) { ipmi_destroy_user(ipmi_device->user_interface); - put_device(ipmi_device->smi_data.dev); + put_device(ipmi_device->dev); kfree(ipmi_device); } @@ -282,7 +280,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, buffer = (struct acpi_ipmi_buffer *)value; /* copy the tx message data */ if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { - dev_WARN_ONCE(&tx_msg->device->pnp_dev->dev, true, + dev_WARN_ONCE(tx_msg->device->dev, true, "Unexpected request (msg len %d).\n", buffer->length); return -EINVAL; @@ -389,11 +387,11 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) struct acpi_ipmi_device *ipmi_device = user_msg_data; bool msg_found = false; struct acpi_ipmi_msg *tx_msg, *temp; - struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; + struct device *dev = ipmi_device->dev; unsigned long flags; if (msg->user != ipmi_device->user_interface) { - dev_warn(&pnp_dev->dev, "Unexpected response is returned. " + dev_warn(dev, "Unexpected response is returned. " "returned user %p, expected user %p\n", msg->user, ipmi_device->user_interface); goto out_msg; @@ -409,14 +407,14 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { - dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " + dev_warn(dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); goto out_msg; } /* copy the response data to Rx_data buffer */ if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) { - dev_WARN_ONCE(&pnp_dev->dev, true, + dev_WARN_ONCE(dev, true, "Unexpected response (msg len %d).\n", msg->msg.data_len); goto out_comp; @@ -426,7 +424,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && msg->msg.data_len == 1) { if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) { - dev_WARN_ONCE(&pnp_dev->dev, true, + dev_WARN_ONCE(dev, true, "Unexpected response (timeout).\n"); tx_msg->msg_done = ACPI_IPMI_TIMEOUT; } @@ -445,7 +443,6 @@ out_msg: static void ipmi_register_bmc(int iface, struct device *dev) { struct acpi_ipmi_device *ipmi_device, *temp; - struct pnp_dev *pnp_dev; int err; struct ipmi_smi_info smi_data; acpi_handle handle; @@ -460,11 +457,10 @@ static void ipmi_register_bmc(int iface, struct device *dev) handle = smi_data.addr_info.acpi_info.acpi_handle; if (!handle) goto err_ref; - pnp_dev = to_pnp_dev(smi_data.dev); - ipmi_device = ipmi_dev_alloc(iface, &smi_data, handle); + ipmi_device = ipmi_dev_alloc(iface, smi_data.dev, handle); if (!ipmi_device) { - dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); + dev_warn(smi_data.dev, "Can't create IPMI user interface\n"); goto err_ref; } -- cgit v1.2.3 From a194aa43272d22f035e6f862db2d714658a02b36 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:31 +0800 Subject: ACPI / IPMI: Cleanup some initialization codes This (trivial) patch. 1. Changes dynamic mutex initialization to static initialization. 2. Removes one acpi_ipmi_init() variable initialization as it is not needed. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 90d57c86db85..f7b6598bd7c2 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -127,6 +127,7 @@ static struct ipmi_driver_data driver_data = { .ipmi_hndlrs = { .ipmi_recv_hndl = ipmi_msg_handler, }, + .ipmi_lock = __MUTEX_INITIALIZER(driver_data.ipmi_lock) }; static struct acpi_ipmi_device * @@ -591,13 +592,11 @@ out_msg: static int __init acpi_ipmi_init(void) { - int result = 0; + int result; acpi_status status; if (acpi_disabled) - return result; - - mutex_init(&driver_data.ipmi_lock); + return 0; status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, -- cgit v1.2.3 From 935a9e3f9d57be122013113318e30e68530b474d Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:41 +0800 Subject: ACPI / IPMI: Cleanup some inclusion codes This (trivial) patch: 1. Deletes several useless header inclusions. 2. Kernel codes should always include instead of or where many conditional declarations are handled. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index f7b6598bd7c2..9d187fdbfd96 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -24,22 +24,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include #include MODULE_AUTHOR("Zhao Yakui"); -- cgit v1.2.3 From 4b88e330914941c86198ca0b48f4ce16f112bbf0 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:51 +0800 Subject: ACPI / IPMI: Cleanup some Kconfig codes This (trivial) patch: 1. Deletes duplicate Kconfig dependency as there is "if IPMI_HANDLER" around "IPMI_SI". Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22327e6a7236..d130e2c115cc 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -175,9 +175,10 @@ config ACPI_PROCESSOR To compile this driver as a module, choose M here: the module will be called processor. + config ACPI_IPMI tristate "IPMI" - depends on IPMI_SI && IPMI_HANDLER + depends on IPMI_SI default n help This driver enables the ACPI to access the BMC controller. And it -- cgit v1.2.3 From 50065300314e95c945665a17febc0c4e02941b06 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:15:00 +0800 Subject: ACPI / IPMI: Cleanup coding styles This patch only introduces indentation cleanups. No functional changes. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_ipmi.c | 105 +++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 40 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 9d187fdbfd96..ac0f52f6df2b 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -33,7 +33,6 @@ MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); MODULE_LICENSE("GPL"); - #define ACPI_IPMI_OK 0 #define ACPI_IPMI_TIMEOUT 0x10 #define ACPI_IPMI_UNKNOWN 0x07 @@ -44,12 +43,14 @@ MODULE_LICENSE("GPL"); struct acpi_ipmi_device { /* the device list attached to driver_data.ipmi_devices */ struct list_head head; + /* the IPMI request message list */ struct list_head tx_msg_list; - spinlock_t tx_msg_lock; + + spinlock_t tx_msg_lock; acpi_handle handle; struct device *dev; - ipmi_user_t user_interface; + ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; bool dead; @@ -57,10 +58,11 @@ struct acpi_ipmi_device { }; struct ipmi_driver_data { - struct list_head ipmi_devices; - struct ipmi_smi_watcher bmc_events; - struct ipmi_user_hndl ipmi_hndlrs; - struct mutex ipmi_lock; + struct list_head ipmi_devices; + struct ipmi_smi_watcher bmc_events; + struct ipmi_user_hndl ipmi_hndlrs; + struct mutex ipmi_lock; + /* * NOTE: IPMI System Interface Selection * There is no system interface specified by the IPMI operation @@ -73,6 +75,7 @@ struct ipmi_driver_data { struct acpi_ipmi_msg { struct list_head head; + /* * General speaking the addr type should be SI_ADDR_TYPE. And * the addr channel should be BMC. @@ -82,15 +85,19 @@ struct acpi_ipmi_msg { */ struct ipmi_addr addr; long tx_msgid; + /* it is used to track whether the IPMI message is finished */ struct completion tx_complete; + struct kernel_ipmi_msg tx_message; - int msg_done; + int msg_done; + /* tx/rx data . And copy it from/to ACPI object buffer */ - u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; - u8 rx_len; + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; + u8 rx_len; + struct acpi_ipmi_device *device; - struct kref kref; + struct kref kref; }; /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */ @@ -132,7 +139,6 @@ ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle) INIT_LIST_HEAD(&ipmi_device->head); INIT_LIST_HEAD(&ipmi_device->tx_msg_list); spin_lock_init(&ipmi_device->tx_msg_lock); - ipmi_device->handle = handle; ipmi_device->dev = get_device(dev); ipmi_device->ipmi_ifnum = iface; @@ -169,6 +175,7 @@ static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) list_del(&ipmi_device->head); if (driver_data.selected_smi == ipmi_device) driver_data.selected_smi = NULL; + /* * Always setting dead flag after deleting from the list or * list_for_each_entry() codes must get changed. @@ -203,16 +210,19 @@ static struct acpi_ipmi_msg *ipmi_msg_alloc(void) ipmi = acpi_ipmi_dev_get(); if (!ipmi) return NULL; + ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL); if (!ipmi_msg) { acpi_ipmi_dev_put(ipmi); return NULL; } + kref_init(&ipmi_msg->kref); init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN; + return ipmi_msg; } @@ -242,11 +252,11 @@ static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg) kref_put(&tx_msg->kref, ipmi_msg_release_kref); } -#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) -#define IPMI_OP_RGN_CMD(offset) (offset & 0xff) +#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) +#define IPMI_OP_RGN_CMD(offset) (offset & 0xff) static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, - acpi_physical_address address, - acpi_integer *value) + acpi_physical_address address, + acpi_integer *value) { struct kernel_ipmi_msg *msg; struct acpi_ipmi_buffer *buffer; @@ -254,6 +264,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, unsigned long flags; msg = &tx_msg->tx_message; + /* * IPMI network function and command are encoded in the address * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3. @@ -261,11 +272,13 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, msg->netfn = IPMI_OP_RGN_NETFN(address); msg->cmd = IPMI_OP_RGN_CMD(address); msg->data = tx_msg->data; + /* * value is the parameter passed by the IPMI opregion space handler. * It points to the IPMI request message buffer */ buffer = (struct acpi_ipmi_buffer *)value; + /* copy the tx message data */ if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { dev_WARN_ONCE(tx_msg->device->dev, true, @@ -275,6 +288,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, } msg->data_len = buffer->length; memcpy(tx_msg->data, buffer->data, msg->data_len); + /* * now the default type is SYSTEM_INTERFACE and channel type is BMC. * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE, @@ -288,15 +302,17 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, /* Get the msgid */ device = tx_msg->device; + spin_lock_irqsave(&device->tx_msg_lock, flags); device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; spin_unlock_irqrestore(&device->tx_msg_lock, flags); + return 0; } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, - acpi_integer *value) + acpi_integer *value) { struct acpi_ipmi_buffer *buffer; @@ -305,6 +321,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, * IPMI message returned by IPMI command. */ buffer = (struct acpi_ipmi_buffer *)value; + /* * If the flag of msg_done is not set, it means that the IPMI command is * not executed correctly. @@ -312,6 +329,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, buffer->status = msg->msg_done; if (msg->msg_done != ACPI_IPMI_OK) return; + /* * If the IPMI response message is obtained correctly, the status code * will be ACPI_IPMI_OK @@ -379,11 +397,12 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) unsigned long flags; if (msg->user != ipmi_device->user_interface) { - dev_warn(dev, "Unexpected response is returned. " - "returned user %p, expected user %p\n", - msg->user, ipmi_device->user_interface); + dev_warn(dev, + "Unexpected response is returned. returned user %p, expected user %p\n", + msg->user, ipmi_device->user_interface); goto out_msg; } + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { @@ -395,8 +414,9 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { - dev_warn(dev, "Unexpected response (msg id %ld) is " - "returned.\n", msg->msgid); + dev_warn(dev, + "Unexpected response (msg id %ld) is returned.\n", + msg->msgid); goto out_msg; } @@ -407,6 +427,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) msg->msg.data_len); goto out_comp; } + /* response msg is an error msg */ msg->recv_type = IPMI_RESPONSE_RECV_TYPE; if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && @@ -418,15 +439,17 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } goto out_comp; } + tx_msg->rx_len = msg->msg.data_len; memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); tx_msg->msg_done = ACPI_IPMI_OK; + out_comp: complete(&tx_msg->tx_complete); acpi_ipmi_msg_put(tx_msg); out_msg: ipmi_free_recv_msg(msg); -}; +} static void ipmi_register_bmc(int iface, struct device *dev) { @@ -436,7 +459,6 @@ static void ipmi_register_bmc(int iface, struct device *dev) acpi_handle handle; err = ipmi_get_smi_info(iface, &smi_data); - if (err) return; @@ -461,11 +483,11 @@ static void ipmi_register_bmc(int iface, struct device *dev) if (temp->handle == handle) goto err_lock; } - if (!driver_data.selected_smi) driver_data.selected_smi = ipmi_device; list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); + put_device(smi_data.dev); return; @@ -484,7 +506,7 @@ static void ipmi_bmc_gone(int iface) mutex_lock(&driver_data.ipmi_lock); list_for_each_entry_safe(ipmi_device, temp, - &driver_data.ipmi_devices, head) { + &driver_data.ipmi_devices, head) { if (ipmi_device->ipmi_ifnum != iface) { dev_found = true; __ipmi_dev_kill(ipmi_device); @@ -496,14 +518,13 @@ static void ipmi_bmc_gone(int iface) &driver_data.ipmi_devices, struct acpi_ipmi_device, head); mutex_unlock(&driver_data.ipmi_lock); + if (dev_found) { ipmi_flush_tx_msg(ipmi_device); acpi_ipmi_dev_put(ipmi_device); } } -/* -------------------------------------------------------------------------- - * Address Space Management - * -------------------------------------------------------------------------- */ + /* * This is the IPMI opregion space handler. * @function: indicates the read/write. In fact as the IPMI message is driven @@ -516,17 +537,17 @@ static void ipmi_bmc_gone(int iface) * the response IPMI message returned by IPMI command. * @handler_context: IPMI device context. */ - static acpi_status acpi_ipmi_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer *value, - void *handler_context, void *region_context) + u32 bits, acpi_integer *value, + void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; unsigned long flags; + /* * IPMI opregion message. * IPMI message is firstly written to the BMC and system software @@ -539,13 +560,13 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, tx_msg = ipmi_msg_alloc(); if (!tx_msg) return AE_NOT_EXIST; - ipmi_device = tx_msg->device; if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { ipmi_msg_release(tx_msg); return AE_TYPE; } + acpi_ipmi_msg_get(tx_msg); mutex_lock(&driver_data.ipmi_lock); /* Do not add a tx_msg that can not be flushed. */ @@ -558,16 +579,18 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); mutex_unlock(&driver_data.ipmi_lock); + err = ipmi_request_settime(ipmi_device->user_interface, - &tx_msg->addr, - tx_msg->tx_msgid, - &tx_msg->tx_message, - NULL, 0, 0, IPMI_TIMEOUT); + &tx_msg->addr, + tx_msg->tx_msgid, + &tx_msg->tx_message, + NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; goto out_msg; } wait_for_completion(&tx_msg->tx_complete); + acpi_format_ipmi_response(tx_msg, value); status = AE_OK; @@ -586,8 +609,9 @@ static int __init acpi_ipmi_init(void) return 0; status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, - NULL, NULL); + ACPI_ADR_SPACE_IPMI, + &acpi_ipmi_space_handler, + NULL, NULL); if (ACPI_FAILURE(status)) { pr_warn("Can't register IPMI opregion space handle\n"); return -EINVAL; @@ -629,7 +653,8 @@ static void __exit acpi_ipmi_exit(void) } mutex_unlock(&driver_data.ipmi_lock); acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); + ACPI_ADR_SPACE_IPMI, + &acpi_ipmi_space_handler); } module_init(acpi_ipmi_init); -- cgit v1.2.3 From 9b5b06740194c8fa1cddb3aa5fe69fd6f5199bc4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:04 -0600 Subject: ACPI / hotplug: Set kobject name via kobject_add(), not kobject_set_name() Set the kobject name via kobject_add() instead of using kobject_set_name(), which is deprecated per Documentation/kobject.txt. Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 05306a59aedc..ea685835b834 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -763,12 +763,9 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, goto err_out; kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - error = kobject_set_name(&hotplug->kobj, "%s", name); - if (error) - goto err_out; hotplug->kobj.parent = hotplug_kobj; - error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL); + error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v1.2.3 From cae712724161c27f5e8c39bb3946449e1c179881 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:12 -0600 Subject: ACPI / hotplug: Don't set kobject parent pointer explicitly kobject_add() sets the parent pointer, so we don't need to do it explicitly. Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index ea685835b834..75432819579c 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -764,7 +764,6 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - hotplug->kobj.parent = hotplug_kobj; error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v1.2.3 From acd3e2c99464c0391885d58dbe7c99a11d4c0289 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:20 -0600 Subject: ACPI / hotplug: Use kobject_init_and_add() instead of _init() and _add() Use kobject_init_and_add() since we have nothing special to do between kobject_init() and kobject_add(). Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 75432819579c..bb6045c5385b 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -762,9 +762,8 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, if (!hotplug_kobj) goto err_out; - kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - - error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); + error = kobject_init_and_add(&hotplug->kobj, + &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v1.2.3 From 766a8a6dd89268107df1f6783f6a6338efcbf07e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 13 Sep 2013 18:15:46 +0300 Subject: ACPI / thermal: convert printk(LEVEL...) to pr_ Convert printks to pr_* format. Additionally re-use PREFIX constant instead of hardcoded strings. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 6a0329340b42..e600b5dbfcb6 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No critical threshold\n")); } else if (tmp <= 2732) { - printk(KERN_WARNING FW_BUG "Invalid critical threshold " - "(%llu)\n", tmp); + pr_warn(FW_BUG "Invalid critical threshold (%llu)\n", + tmp); tz->trips.critical.flags.valid = 0; } else { tz->trips.critical.flags.valid = 1; @@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) * Allow override critical threshold */ if (crt_k > tz->trips.critical.temperature) - printk(KERN_WARNING PREFIX - "Critical threshold %d C\n", crt); + pr_warn(PREFIX "Critical threshold %d C\n", + crt); tz->trips.critical.temperature = crt_k; } } @@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PREFIX - "Invalid passive threshold\n"); + pr_warn(PREFIX "Invalid passive threshold\n"); tz->trips.passive.flags.valid = 0; } else @@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PREFIX - "Invalid active%d threshold\n", i); + pr_warn(PREFIX "Invalid active%d threshold\n", + i); tz->trips.active[i].flags.valid = 0; } else @@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) valid |= tz->trips.active[i].flags.valid; if (!valid) { - printk(KERN_WARNING FW_BUG "No valid trip found\n"); + pr_warn(FW_BUG "No valid trip found\n"); return -ENODEV; } return 0; @@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_bus_private_data_handler, tz->thermal_zone); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Error attaching device data\n"); + pr_err(PREFIX "Error attaching device data\n"); return -ENODEV; } @@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto free_memory; - printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", - acpi_device_name(device), acpi_device_bid(device), - KELVIN_TO_CELSIUS(tz->temperature)); + pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), + acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); goto end; free_memory: @@ -1159,24 +1156,24 @@ static int acpi_thermal_resume(struct device *dev) static int thermal_act(const struct dmi_system_id *d) { if (act == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all active thermal trip points\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all active thermal trip points\n", d->ident); act = -1; } return 0; } static int thermal_nocrt(const struct dmi_system_id *d) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all critical thermal trip point actions.\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all critical thermal trip point actions.\n", d->ident); nocrt = 1; return 0; } static int thermal_tzp(const struct dmi_system_id *d) { if (tzp == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "enabling thermal zone polling\n", d->ident); + pr_notice(PREFIX "%s detected: " + "enabling thermal zone polling\n", d->ident); tzp = 300; /* 300 dS = 30 Seconds */ } return 0; @@ -1184,8 +1181,8 @@ static int thermal_tzp(const struct dmi_system_id *d) { static int thermal_psv(const struct dmi_system_id *d) { if (psv == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all passive thermal trip points\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all passive thermal trip points\n", d->ident); psv = -1; } return 0; @@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void) dmi_check_system(thermal_dmi_table); if (off) { - printk(KERN_NOTICE "ACPI: thermal control disabled\n"); + pr_notice(PREFIX "thermal control disabled\n"); return -ENODEV; } -- cgit v1.2.3 From 6585925b62fa4dd2f4aecf634b0f8956577aa981 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 1 Oct 2013 23:02:43 +0200 Subject: ACPI: Use EXPORT_SYMBOL() for acpi_bus_get_device() Commit caf5c03f (ACPI: Move acpi_bus_get_device() from bus.c to scan.c) caused acpi_bus_get_device() to be exported using EXPORT_SYMBOL_GPL(), but that broke some binary drivers in existence, so revert that change. Reported-by: Peter Hurley Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 611ce9061dc5..407ad13cac2f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -968,7 +968,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) } return 0; } -EXPORT_SYMBOL_GPL(acpi_bus_get_device); +EXPORT_SYMBOL(acpi_bus_get_device); int acpi_device_add(struct acpi_device *device, void (*release)(struct device *)) -- cgit v1.2.3 From 764d022133979f9d9a179152cd89717e9752c61a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Rh=C3=A9aume?= Date: Tue, 1 Oct 2013 05:29:39 -0400 Subject: ACPI / processor: fixed a brace coding style issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed a brace coding style issue. (Brace not on the good line) Signed-off-by: Mathieu Rhéaume Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e534ba66d5b8..40fc773ab6e0 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -153,8 +153,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __refdata acpi_cpu_notifier = -{ +static struct notifier_block __refdata acpi_cpu_notifier = { .notifier_call = acpi_cpu_soft_notify, }; -- cgit v1.2.3 From b4cb9244a544a1623305eb58267a90418268d31e Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Thu, 3 Oct 2013 12:13:03 -0500 Subject: ACPI: update win8 OSI blacklist More people have reported they need this for their machines to work correctly. References: https://bugzilla.kernel.org/show_bug.cgi?id=60682 Reported-by: Stefan Hellermann Reported-by: Benedikt Sauer Reported-by: Erno Kuusela Reported-by: Jonathan Doman Reported-by: Christoph Klaffl Reported-by: Jan Hendrik Nielsen Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9515f18898b2..f37dec579712 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -297,6 +297,54 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), }, }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Acer Aspire V5-573G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Acer Aspire V5-572G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad T431s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad T430", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From 068aab7766cf968a8ddb86a6d7c6bbed9d61e353 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sun, 6 Oct 2013 20:59:55 -0500 Subject: ACPI: add missing win8 OSI comment to blacklist In my original patch[1] I wrote a comment describing the reason for disabling Windows 2012 OSI mode for a group of machines, however, due to unknown reasons (probably a conflict resolution mismatch), the comment was dropped in 94fb982 (ACPI: blacklist win8 OSI for buggy laptops). Since Matthew Garrett is making a big deal out of the lack of comments in a separate patch[2], it might make sense to re-introduce the missing comment so that other patch is not blocked and users don't suffer. [1] http://article.gmane.org/gmane.linux.acpi.devel/63427 [2] http://thread.gmane.org/gmane.linux.kernel/1572459 Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index f37dec579712..aa4d874a96fd 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + + /* + * The following machines have broken backlight support when reporting + * the Windows 2012 OSI, so disable it until their support is fixed. + */ { .callback = dmi_disable_osi_win8, .ident = "ASUS Zenbook Prime UX31A", -- cgit v1.2.3 From 16ff816d3b5d2b81fcff5ca44eb9a98ac3b604b4 Mon Sep 17 00:00:00 2001 From: Zhang Yanfei Date: Wed, 2 Oct 2013 16:27:37 +0800 Subject: ACPI / memhotplug: Use defined marco METHOD_NAME__STA We already have predefined marco for method name "_STA', so using the marco instead of directly using the string. Signed-off-by: Zhang Yanfei Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_memhotplug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 999adb5499c7..dc0880db909c 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -152,8 +152,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device) unsigned long long current_status; /* Get device present/absent information from the _STA */ - if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA", - NULL, ¤t_status))) + if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, + METHOD_NAME__STA, NULL, + ¤t_status))) return -ENODEV; /* * Check for device status. Device should be -- cgit v1.2.3 From e54968ca1eaa78749d7a7fc20227639a31dff629 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 7 Oct 2013 17:12:21 +0300 Subject: ACPI / platform: Add ACPI IDs for Intel SST audio device This adds ACPI IDs for Intel Smart Sound Technology (SST) device found in Intel Haswell and BayTrail platforms. Signed-off-by: Jarkko Nikula Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_platform.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1bde12708f9e..ed0f06390245 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -30,6 +30,9 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, + /* Intel Smart Sound Technology */ + { "INT33C8" }, + { "80860F28" }, { } }; -- cgit v1.2.3 From 088f1fd267c7f43b5d87850a0fa0c7e851ecae97 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 9 Oct 2013 09:49:20 +0300 Subject: ACPI / LPSS: fix UART Auto Flow Control There is an additional bit in the GENERAL register on newer silicon that needs to be set or UART's RTS pin fails to reflect the flow control settings in the Modem Control Register. This will fix an issue where the RTS pin of the UART stays always at 1.8V, regardless of the register settings. Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index fb78bb9ad8f6..d3961014aad7 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss"); /* Offsets relative to LPSS_PRIVATE_OFFSET */ #define LPSS_GENERAL 0x08 #define LPSS_GENERAL_LTR_MODE_SW BIT(2) +#define LPSS_GENERAL_UART_RTS_OVRD BIT(3) #define LPSS_SW_LTR 0x10 #define LPSS_AUTO_LTR 0x14 #define LPSS_TX_INT 0x20 @@ -68,11 +69,16 @@ struct lpss_private_data { static void lpss_uart_setup(struct lpss_private_data *pdata) { - unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + unsigned int offset; u32 reg; - reg = readl(pdata->mmio_base + tx_int_offset); - writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset); + offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + reg = readl(pdata->mmio_base + offset); + writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset); + + offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; + reg = readl(pdata->mmio_base + offset); + writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset); } static struct lpss_device_desc lpt_dev_desc = { -- cgit v1.2.3 From e83dda06242073b1c7f9a88f1001e32a4b9fcd1d Mon Sep 17 00:00:00 2001 From: Al Stone Date: Wed, 9 Oct 2013 14:21:10 -0600 Subject: ACPI: improve acpi_extract_package() utility The current version requires one to know the size of the package a priori; this is almost impossible if the package is composed of strings of variable length. This change allows the utility to allocate a buffer of the proper size if asked. Signed-off-by: Al Stone Signed-off-by: Rafael J. Wysocki --- drivers/acpi/utils.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 552248b0005b..fc2cd3284080 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -169,11 +169,20 @@ acpi_extract_package(union acpi_object *package, /* * Validate output buffer. */ - if (buffer->length < size_required) { + if (buffer->length == ACPI_ALLOCATE_BUFFER) { + buffer->pointer = ACPI_ALLOCATE(size_required); + if (!buffer->pointer) + return AE_NO_MEMORY; buffer->length = size_required; - return AE_BUFFER_OVERFLOW; - } else if (buffer->length != size_required || !buffer->pointer) { - return AE_BAD_PARAMETER; + memset(buffer->pointer, 0, size_required); + } else { + if (buffer->length < size_required) { + buffer->length = size_required; + return AE_BUFFER_OVERFLOW; + } else if (buffer->length != size_required || + !buffer->pointer) { + return AE_BAD_PARAMETER; + } } head = buffer->pointer; -- cgit v1.2.3 From 644f17ad7fc12768cd619532383343e514eab2ac Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 10 Oct 2013 13:28:46 +0300 Subject: ACPI / PM: allow child devices to ignore parent power state Some serial buses like I2C and SPI don't require that the parent device is in D0 before any of its children transitions to D0, but instead the parent device can control its own power independently from the children. This does not follow the ACPI specification as it requires the parent to be powered on before its children. However, Windows seems to ignore this requirement so I think we can do the same in Linux. Implement this by adding a new power flag 'ignore_parent' to struct acpi_device. If this flag is set the ACPI core ignores checking of the parent device power state when the device is powered on/off. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 59d3202f6b36..ca723a4c120a 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state) /* * If we were unsure about the device parent's power state up to this * point, the fact that the device is in D0 implies that the parent has - * to be in D0 too. + * to be in D0 too, except if ignore_parent is set. */ - if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN + if (!device->power.flags.ignore_parent && device->parent + && device->parent->power.state == ACPI_STATE_UNKNOWN && result == ACPI_STATE_D0) device->parent->power.state = ACPI_STATE_D0; @@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) acpi_power_state_string(state)); return -ENODEV; } - if (device->parent && (state < device->parent->power.state)) { + if (!device->power.flags.ignore_parent && + device->parent && (state < device->parent->power.state)) { dev_warn(&device->dev, "Cannot transition to power state %s for parent in %s\n", acpi_power_state_string(state), -- cgit v1.2.3 From aaf3d29fe8c888f3fc1b5e00d66085fe4e06e4cb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 10 Oct 2013 23:25:58 +0200 Subject: ACPI / PM / Documentation: Replace outdated project links and addresses Some links to projects web pages and e-mail addresses in ACPI/PM documentation and Kconfig are outdated, so update them. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22327e6a7236..5ea5c32609ac 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -24,7 +24,7 @@ menuconfig ACPI are configured, ACPI is used. The project home page for the Linux ACPI subsystem is here: - + Linux support for ACPI is based on Intel Corporation's ACPI Component Architecture (ACPI CA). For more information on the -- cgit v1.2.3 From 1e2d9cdfb4494fce682b4ae010d86a2766816d36 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:08 +0800 Subject: ACPI / Battery: Remove battery's proc directory The battery's proc directory isn't useded and remove it. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 328 +------------------------------------------------ 1 file changed, 1 insertion(+), 327 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2c9958cd7a43..fbf1aceda8b8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -36,12 +36,6 @@ #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#include -#endif - #include #include #include @@ -72,19 +66,6 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -#ifdef CONFIG_ACPI_PROCFS_POWER -extern struct proc_dir_entry *acpi_lock_battery_dir(void); -extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); - -enum acpi_battery_files { - info_tag = 0, - state_tag, - alarm_tag, - ACPI_BATTERY_NUMFILES, -}; - -#endif - static const struct acpi_device_id battery_device_ids[] = { {"PNP0C0A", 0}, {"", 0}, @@ -320,14 +301,6 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_SERIAL_NUMBER, }; -#ifdef CONFIG_ACPI_PROCFS_POWER -inline char *acpi_battery_units(struct acpi_battery *battery) -{ - return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? - "mA" : "mW"; -} -#endif - /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ @@ -740,279 +713,6 @@ static void acpi_battery_refresh(struct acpi_battery *battery) sysfs_add_battery(battery); } -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS_POWER -static struct proc_dir_entry *acpi_battery_dir; - -static int acpi_battery_print_info(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - seq_printf(seq, "present: %s\n", - acpi_battery_present(battery) ? "yes" : "no"); - if (!acpi_battery_present(battery)) - goto end; - if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "design capacity: unknown\n"); - else - seq_printf(seq, "design capacity: %d %sh\n", - battery->design_capacity, - acpi_battery_units(battery)); - - if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "last full capacity: unknown\n"); - else - seq_printf(seq, "last full capacity: %d %sh\n", - battery->full_charge_capacity, - acpi_battery_units(battery)); - - seq_printf(seq, "battery technology: %srechargeable\n", - (!battery->technology)?"non-":""); - - if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "design voltage: unknown\n"); - else - seq_printf(seq, "design voltage: %d mV\n", - battery->design_voltage); - seq_printf(seq, "design capacity warning: %d %sh\n", - battery->design_capacity_warning, - acpi_battery_units(battery)); - seq_printf(seq, "design capacity low: %d %sh\n", - battery->design_capacity_low, - acpi_battery_units(battery)); - seq_printf(seq, "cycle count: %i\n", battery->cycle_count); - seq_printf(seq, "capacity granularity 1: %d %sh\n", - battery->capacity_granularity_1, - acpi_battery_units(battery)); - seq_printf(seq, "capacity granularity 2: %d %sh\n", - battery->capacity_granularity_2, - acpi_battery_units(battery)); - seq_printf(seq, "model number: %s\n", battery->model_number); - seq_printf(seq, "serial number: %s\n", battery->serial_number); - seq_printf(seq, "battery type: %s\n", battery->type); - seq_printf(seq, "OEM info: %s\n", battery->oem_info); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery info\n"); - return result; -} - -static int acpi_battery_print_state(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - seq_printf(seq, "present: %s\n", - acpi_battery_present(battery) ? "yes" : "no"); - if (!acpi_battery_present(battery)) - goto end; - - seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x04) ? "critical" : "ok"); - if ((battery->state & 0x01) && (battery->state & 0x02)) - seq_printf(seq, - "charging state: charging/discharging\n"); - else if (battery->state & 0x01) - seq_printf(seq, "charging state: discharging\n"); - else if (battery->state & 0x02) - seq_printf(seq, "charging state: charging\n"); - else - seq_printf(seq, "charging state: charged\n"); - - if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "present rate: unknown\n"); - else - seq_printf(seq, "present rate: %d %s\n", - battery->rate_now, acpi_battery_units(battery)); - - if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "remaining capacity: unknown\n"); - else - seq_printf(seq, "remaining capacity: %d %sh\n", - battery->capacity_now, acpi_battery_units(battery)); - if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "present voltage: unknown\n"); - else - seq_printf(seq, "present voltage: %d mV\n", - battery->voltage_now); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery state\n"); - - return result; -} - -static int acpi_battery_print_alarm(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - if (!acpi_battery_present(battery)) { - seq_printf(seq, "present: no\n"); - goto end; - } - seq_printf(seq, "alarm: "); - if (!battery->alarm) - seq_printf(seq, "unsupported\n"); - else - seq_printf(seq, "%u %sh\n", battery->alarm, - acpi_battery_units(battery)); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery alarm\n"); - return result; -} - -static ssize_t acpi_battery_write_alarm(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) -{ - int result = 0; - char alarm_string[12] = { '\0' }; - struct seq_file *m = file->private_data; - struct acpi_battery *battery = m->private; - - if (!battery || (count > sizeof(alarm_string) - 1)) - return -EINVAL; - if (!acpi_battery_present(battery)) { - result = -ENODEV; - goto end; - } - if (copy_from_user(alarm_string, buffer, count)) { - result = -EFAULT; - goto end; - } - alarm_string[count] = '\0'; - battery->alarm = simple_strtol(alarm_string, NULL, 0); - result = acpi_battery_set_alarm(battery); - end: - if (!result) - return count; - return result; -} - -typedef int(*print_func)(struct seq_file *seq, int result); - -static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { - acpi_battery_print_info, - acpi_battery_print_state, - acpi_battery_print_alarm, -}; - -static int acpi_battery_read(int fid, struct seq_file *seq) -{ - struct acpi_battery *battery = seq->private; - int result = acpi_battery_update(battery); - return acpi_print_funcs[fid](seq, result); -} - -#define DECLARE_FILE_FUNCTIONS(_name) \ -static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ -{ \ - return acpi_battery_read(_name##_tag, seq); \ -} \ -static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \ -} - -DECLARE_FILE_FUNCTIONS(info); -DECLARE_FILE_FUNCTIONS(state); -DECLARE_FILE_FUNCTIONS(alarm); - -#undef DECLARE_FILE_FUNCTIONS - -#define FILE_DESCRIPTION_RO(_name) \ - { \ - .name = __stringify(_name), \ - .mode = S_IRUGO, \ - .ops = { \ - .open = acpi_battery_##_name##_open_fs, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - .owner = THIS_MODULE, \ - }, \ - } - -#define FILE_DESCRIPTION_RW(_name) \ - { \ - .name = __stringify(_name), \ - .mode = S_IFREG | S_IRUGO | S_IWUSR, \ - .ops = { \ - .open = acpi_battery_##_name##_open_fs, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .write = acpi_battery_write_##_name, \ - .release = single_release, \ - .owner = THIS_MODULE, \ - }, \ - } - -static const struct battery_file { - struct file_operations ops; - umode_t mode; - const char *name; -} acpi_battery_file[] = { - FILE_DESCRIPTION_RO(info), - FILE_DESCRIPTION_RO(state), - FILE_DESCRIPTION_RW(alarm), -}; - -#undef FILE_DESCRIPTION_RO -#undef FILE_DESCRIPTION_RW - -static int acpi_battery_add_fs(struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - int i; - - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_battery_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - } - - for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { - entry = proc_create_data(acpi_battery_file[i].name, - acpi_battery_file[i].mode, - acpi_device_dir(device), - &acpi_battery_file[i].ops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - } - return 0; -} - -static void acpi_battery_remove_fs(struct acpi_device *device) -{ - int i; - if (!acpi_device_dir(device)) - return; - for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) - remove_proc_entry(acpi_battery_file[i].name, - acpi_device_dir(device)); - - remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); - acpi_device_dir(device) = NULL; -} - -#endif - /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -1075,15 +775,6 @@ static int acpi_battery_add(struct acpi_device *device) result = acpi_battery_update(battery); if (result) goto fail; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_battery_add_fs(device); -#endif - if (result) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_remove_fs(device); -#endif - goto fail; - } printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), @@ -1110,9 +801,6 @@ static int acpi_battery_remove(struct acpi_device *device) return -EINVAL; battery = acpi_driver_data(device); unregister_pm_notifier(&battery->pm_nb); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_remove_fs(device); -#endif sysfs_remove_battery(battery); mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); @@ -1158,18 +846,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) { if (acpi_disabled) return; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_dir = acpi_lock_battery_dir(); - if (!acpi_battery_dir) - return; -#endif - if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_battery_dir(acpi_battery_dir); -#endif - return; - } - return; + acpi_bus_register_driver(&acpi_battery_driver); } static int __init acpi_battery_init(void) @@ -1181,9 +858,6 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_battery_dir(acpi_battery_dir); -#endif } module_init(acpi_battery_init); -- cgit v1.2.3 From 2a68b995c8d5d36de50fd2a7c9c594d986f04c87 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:09 +0800 Subject: ACPI / SBS: Remove SBS's proc directory SBS's proc directory isn't useded and so remove it. Prepare for removing /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sbs.c | 325 +---------------------------------------------------- 1 file changed, 4 insertions(+), 321 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index aef7e1cd1e5d..d465ae6cdd00 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -30,12 +30,6 @@ #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#include -#endif - #include #include #include @@ -67,11 +61,6 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -extern struct proc_dir_entry *acpi_lock_ac_dir(void); -extern struct proc_dir_entry *acpi_lock_battery_dir(void); -extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); -extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); - #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 @@ -84,9 +73,6 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { struct power_supply bat; struct acpi_sbs *sbs; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *proc_entry; -#endif unsigned long update_time; char name[8]; char manufacturer_name[ACPI_SBS_BLOCK_MAX]; @@ -119,9 +105,6 @@ struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *charger_entry; -#endif struct acpi_battery battery[MAX_SBS_BAT]; u8 batteries_supported:4; u8 manager_present:1; @@ -481,261 +464,6 @@ static struct device_attribute alarm_attr = { .store = acpi_battery_alarm_store, }; -/* -------------------------------------------------------------------------- - FS Interface (/proc/acpi) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS_POWER -/* Generic Routines */ -static int -acpi_sbs_add_fs(struct proc_dir_entry **dir, - struct proc_dir_entry *parent_dir, - char *dir_name, - const struct file_operations *info_fops, - const struct file_operations *state_fops, - const struct file_operations *alarm_fops, void *data) -{ - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!*dir) { - *dir = proc_mkdir(dir_name, parent_dir); - if (!*dir) { - return -ENODEV; - } - } - - /* 'info' [R] */ - if (info_fops) - proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir, - info_fops, data); - - /* 'state' [R] */ - if (state_fops) - proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir, - state_fops, data); - - /* 'alarm' [R/W] */ - if (alarm_fops) - proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir, - alarm_fops, data); - return 0; -} - -/* Smart Battery Interface */ -static struct proc_dir_entry *acpi_battery_dir = NULL; - -static inline char *acpi_battery_units(struct acpi_battery *battery) -{ - return acpi_battery_mode(battery) ? " mW" : " mA"; -} - - -static int acpi_battery_read_info(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - seq_printf(seq, "design capacity: %i%sh\n", - battery->design_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "last full capacity: %i%sh\n", - battery->full_charge_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "battery technology: rechargeable\n"); - seq_printf(seq, "design voltage: %i mV\n", - battery->design_voltage * acpi_battery_vscale(battery)); - seq_printf(seq, "design capacity warning: unknown\n"); - seq_printf(seq, "design capacity low: unknown\n"); - seq_printf(seq, "cycle count: %i\n", battery->cycle_count); - seq_printf(seq, "capacity granularity 1: unknown\n"); - seq_printf(seq, "capacity granularity 2: unknown\n"); - seq_printf(seq, "model number: %s\n", battery->device_name); - seq_printf(seq, "serial number: %i\n", - battery->serial_number); - seq_printf(seq, "battery type: %s\n", - battery->device_chemistry); - seq_printf(seq, "OEM info: %s\n", - battery->manufacturer_name); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_info, PDE_DATA(inode)); -} - -static int acpi_battery_read_state(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int rate; - - mutex_lock(&sbs->lock); - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - acpi_battery_get_state(battery); - seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x0010) ? "critical" : "ok"); - seq_printf(seq, "charging state: %s\n", - (battery->rate_now < 0) ? "discharging" : - ((battery->rate_now > 0) ? "charging" : "charged")); - rate = abs(battery->rate_now) * acpi_battery_ipscale(battery); - rate *= (acpi_battery_mode(battery))?(battery->voltage_now * - acpi_battery_vscale(battery)/1000):1; - seq_printf(seq, "present rate: %d%s\n", rate, - acpi_battery_units(battery)); - seq_printf(seq, "remaining capacity: %i%sh\n", - battery->capacity_now * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "present voltage: %i mV\n", - battery->voltage_now * acpi_battery_vscale(battery)); - - end: - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_state, PDE_DATA(inode)); -} - -static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - if (!battery->present) { - seq_printf(seq, "present: no\n"); - goto end; - } - - acpi_battery_get_alarm(battery); - seq_printf(seq, "alarm: "); - if (battery->alarm_capacity) - seq_printf(seq, "%i%sh\n", - battery->alarm_capacity * - acpi_battery_scale(battery), - acpi_battery_units(battery)); - else - seq_printf(seq, "disabled\n"); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static ssize_t -acpi_battery_write_alarm(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct seq_file *seq = file->private_data; - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - char alarm_string[12] = { '\0' }; - int result = 0; - mutex_lock(&sbs->lock); - if (!battery->present) { - result = -ENODEV; - goto end; - } - if (count > sizeof(alarm_string) - 1) { - result = -EINVAL; - goto end; - } - if (copy_from_user(alarm_string, buffer, count)) { - result = -EFAULT; - goto end; - } - alarm_string[count] = 0; - battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / - acpi_battery_scale(battery); - acpi_battery_set_alarm(battery); - end: - mutex_unlock(&sbs->lock); - if (result) - return result; - return count; -} - -static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode)); -} - -static const struct file_operations acpi_battery_info_fops = { - .open = acpi_battery_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_state_fops = { - .open = acpi_battery_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_alarm_fops = { - .open = acpi_battery_alarm_open_fs, - .read = seq_read, - .write = acpi_battery_write_alarm, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -/* Legacy AC Adapter Interface */ - -static struct proc_dir_entry *acpi_ac_dir = NULL; - -static int acpi_ac_read_state(struct seq_file *seq, void *offset) -{ - - struct acpi_sbs *sbs = seq->private; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "state: %s\n", - sbs->charger_present ? "on-line" : "off-line"); - - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_ac_read_state, PDE_DATA(inode)); -} - -static const struct file_operations acpi_ac_state_fops = { - .open = acpi_ac_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -#endif - /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -781,12 +509,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, - battery->name, &acpi_battery_info_fops, - &acpi_battery_state_fops, &acpi_battery_alarm_fops, - battery); -#endif battery->bat.name = battery->name; battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { @@ -822,10 +544,6 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id) device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); } -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(battery->proc_entry); - battery->proc_entry = NULL; -#endif } static int acpi_charger_add(struct acpi_sbs *sbs) @@ -835,13 +553,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) result = acpi_ac_get_present(sbs); if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, - ACPI_AC_DIR_NAME, NULL, - &acpi_ac_state_fops, NULL, sbs); - if (result) - goto end; -#endif + sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; @@ -859,10 +571,6 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(sbs->charger_entry); - sbs->charger_entry = NULL; -#endif } static void acpi_sbs_callback(void *context) @@ -950,20 +658,6 @@ static int acpi_sbs_remove(struct acpi_device *device) return 0; } -static void acpi_sbs_rmdirs(void) -{ -#ifdef CONFIG_ACPI_PROCFS_POWER - if (acpi_ac_dir) { - acpi_unlock_ac_dir(acpi_ac_dir); - acpi_ac_dir = NULL; - } - if (acpi_battery_dir) { - acpi_unlock_battery_dir(acpi_battery_dir); - acpi_battery_dir = NULL; - } -#endif -} - #ifdef CONFIG_PM_SLEEP static int acpi_sbs_resume(struct device *dev) { @@ -995,28 +689,17 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) - return -ENODEV; - acpi_battery_dir = acpi_lock_battery_dir(); - if (!acpi_battery_dir) { - acpi_sbs_rmdirs(); - return -ENODEV; - } -#endif + result = acpi_bus_register_driver(&acpi_sbs_driver); - if (result < 0) { - acpi_sbs_rmdirs(); + if (result < 0) return -ENODEV; - } + return 0; } static void __exit acpi_sbs_exit(void) { acpi_bus_unregister_driver(&acpi_sbs_driver); - acpi_sbs_rmdirs(); return; } -- cgit v1.2.3 From 7d7ee958867ad3c9c829a36c56e870879e83391f Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:10 +0800 Subject: ACPI: Remove CONFIG_ACPI_PROCFS_POWER and cm_sbsc.c There is no user of cm_sbs.c and CONFIG_ACPI_PROCFS_POWER. So remove them. Prepare for removing /proc/acpi Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 17 -------- drivers/acpi/Makefile | 1 - drivers/acpi/cm_sbs.c | 105 -------------------------------------------------- 3 files changed, 123 deletions(-) delete mode 100644 drivers/acpi/cm_sbs.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22327e6a7236..76f9ebda9081 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -56,23 +56,6 @@ config ACPI_PROCFS Say N to delete /proc/acpi/ files that have moved to /sys/ -config ACPI_PROCFS_POWER - bool "Deprecated power /proc/acpi directories" - depends on PROC_FS - help - For backwards compatibility, this option allows - deprecated power /proc/acpi/ directories to exist, even when - they have been replaced by functions in /sys. - The deprecated directories (and their replacements) include: - /proc/acpi/battery/* (/sys/class/power_supply/*) - /proc/acpi/ac_adapter/* (sys/class/power_supply/*) - This option has no effect on /proc/acpi/ directories - and functions, which do not yet exist in /sys - This option, together with the proc directories, will be - deleted in 2.6.39. - - Say N to delete power /proc/acpi/ directories that have moved to /sys/ - config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index cdaf68b58b00..a55fc06db4ae 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,7 +47,6 @@ acpi-y += sysfs.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o -acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c deleted file mode 100644 index 6c9ee68e46fb..000000000000 --- a/drivers/acpi/cm_sbs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "ACPI: " - -ACPI_MODULE_NAME("cm_sbs"); -#define ACPI_AC_CLASS "ac_adapter" -#define ACPI_BATTERY_CLASS "battery" -#define _COMPONENT ACPI_SBS_COMPONENT -static struct proc_dir_entry *acpi_ac_dir; -static struct proc_dir_entry *acpi_battery_dir; - -static DEFINE_MUTEX(cm_sbs_mutex); - -static int lock_ac_dir_cnt; -static int lock_battery_dir_cnt; - -struct proc_dir_entry *acpi_lock_ac_dir(void) -{ - mutex_lock(&cm_sbs_mutex); - if (!acpi_ac_dir) - acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); - if (acpi_ac_dir) { - lock_ac_dir_cnt++; - } else { - printk(KERN_ERR PREFIX - "Cannot create %s\n", ACPI_AC_CLASS); - } - mutex_unlock(&cm_sbs_mutex); - return acpi_ac_dir; -} -EXPORT_SYMBOL(acpi_lock_ac_dir); - -void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param) -{ - mutex_lock(&cm_sbs_mutex); - if (acpi_ac_dir_param) - lock_ac_dir_cnt--; - if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) { - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); - acpi_ac_dir = NULL; - } - mutex_unlock(&cm_sbs_mutex); -} -EXPORT_SYMBOL(acpi_unlock_ac_dir); - -struct proc_dir_entry *acpi_lock_battery_dir(void) -{ - mutex_lock(&cm_sbs_mutex); - if (!acpi_battery_dir) { - acpi_battery_dir = - proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); - } - if (acpi_battery_dir) { - lock_battery_dir_cnt++; - } else { - printk(KERN_ERR PREFIX - "Cannot create %s\n", ACPI_BATTERY_CLASS); - } - mutex_unlock(&cm_sbs_mutex); - return acpi_battery_dir; -} -EXPORT_SYMBOL(acpi_lock_battery_dir); - -void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) -{ - mutex_lock(&cm_sbs_mutex); - if (acpi_battery_dir_param) - lock_battery_dir_cnt--; - if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param - && acpi_battery_dir) { - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); - acpi_battery_dir = NULL; - } - mutex_unlock(&cm_sbs_mutex); - return; -} -EXPORT_SYMBOL(acpi_unlock_battery_dir); -- cgit v1.2.3 From 7744da5e90a2782ff0d48628c2cb120efcd300f3 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:11 +0800 Subject: ACPI / proc: Remove alarm proc file Alarm proc file provides the info and control of RTC-CMOS alarm and RTC CMOS driver provides wakealarm sysfs attribute for the same purpose. The alarm file isn't compiled into kernel when RTC CMOS driver is selected. The driver is default to be selected for x86 platform. So alarm file is default not to include. This patch is to remove it to prepare remove /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/proc.c | 305 ---------------------------------------------------- 1 file changed, 305 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 04a13784dd20..6a5b152ad4d0 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -8,289 +8,17 @@ #include #include -#ifdef CONFIG_X86 -#include -#endif - #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT /* * this file provides support for: - * /proc/acpi/alarm * /proc/acpi/wakeup */ ACPI_MODULE_NAME("sleep") -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) -/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ -#else -#define HAVE_ACPI_LEGACY_ALARM -#endif - -#ifdef HAVE_ACPI_LEGACY_ALARM - -static u32 cmos_bcd_read(int offset, int rtc_control); - -static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) -{ - u32 sec, min, hr; - u32 day, mo, yr, cent = 0; - u32 today = 0; - unsigned char rtc_control = 0; - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - - rtc_control = CMOS_READ(RTC_CONTROL); - sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control); - min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control); - hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control); - - /* If we ever get an FACP with proper values... */ - if (acpi_gbl_FADT.day_alarm) { - /* ACPI spec: only low 6 its should be cared */ - day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - day = bcd2bin(day); - } else - day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - if (acpi_gbl_FADT.month_alarm) - mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control); - else { - mo = cmos_bcd_read(RTC_MONTH, rtc_control); - today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - } - if (acpi_gbl_FADT.century) - cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control); - - yr = cmos_bcd_read(RTC_YEAR, rtc_control); - - spin_unlock_irqrestore(&rtc_lock, flags); - - /* we're trusting the FADT (see above) */ - if (!acpi_gbl_FADT.century) - /* If we're not trusting the FADT, we should at least make it - * right for _this_ century... ehm, what is _this_ century? - * - * TBD: - * ASAP: find piece of code in the kernel, e.g. star tracker driver, - * which we can trust to determine the century correctly. Atom - * watch driver would be nice, too... - * - * if that has not happened, change for first release in 2050: - * if (yr<50) - * yr += 2100; - * else - * yr += 2000; // current line of code - * - * if that has not happened either, please do on 2099/12/31:23:59:59 - * s/2000/2100 - * - */ - yr += 2000; - else - yr += cent * 100; - - /* - * Show correct dates for alarms up to a month into the future. - * This solves issues for nearly all situations with the common - * 30-day alarm clocks in PC hardware. - */ - if (day < today) { - if (mo < 12) { - mo += 1; - } else { - mo = 1; - yr += 1; - } - } - - seq_printf(seq, "%4.4u-", yr); - (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); - (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); - (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); - (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); - (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); - - return 0; -} - -static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode)); -} - -static int get_date_field(char **p, u32 * value) -{ - char *next = NULL; - char *string_end = NULL; - int result = -EINVAL; - - /* - * Try to find delimeter, only to insert null. The end of the - * string won't have one, but is still valid. - */ - if (*p == NULL) - return result; - - next = strpbrk(*p, "- :"); - if (next) - *next++ = '\0'; - - *value = simple_strtoul(*p, &string_end, 10); - - /* Signal success if we got a good digit */ - if (string_end != *p) - result = 0; - - if (next) - *p = next; - else - *p = NULL; - - return result; -} - -/* Read a possibly BCD register, always return binary */ -static u32 cmos_bcd_read(int offset, int rtc_control) -{ - u32 val = CMOS_READ(offset); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bcd2bin(val); - return val; -} - -/* Write binary value into possibly BCD register */ -static void cmos_bcd_write(u32 val, int offset, int rtc_control) -{ - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bin2bcd(val); - CMOS_WRITE(val, offset); -} - -static ssize_t -acpi_system_write_alarm(struct file *file, - const char __user * buffer, size_t count, loff_t * ppos) -{ - int result = 0; - char alarm_string[30] = { '\0' }; - char *p = alarm_string; - u32 sec, min, hr, day, mo, yr; - int adjust = 0; - unsigned char rtc_control = 0; - - if (count > sizeof(alarm_string) - 1) - return -EINVAL; - - if (copy_from_user(alarm_string, buffer, count)) - return -EFAULT; - - alarm_string[count] = '\0'; - - /* check for time adjustment */ - if (alarm_string[0] == '+') { - p++; - adjust = 1; - } - - if ((result = get_date_field(&p, &yr))) - goto end; - if ((result = get_date_field(&p, &mo))) - goto end; - if ((result = get_date_field(&p, &day))) - goto end; - if ((result = get_date_field(&p, &hr))) - goto end; - if ((result = get_date_field(&p, &min))) - goto end; - if ((result = get_date_field(&p, &sec))) - goto end; - - spin_lock_irq(&rtc_lock); - - rtc_control = CMOS_READ(RTC_CONTROL); - - if (adjust) { - yr += cmos_bcd_read(RTC_YEAR, rtc_control); - mo += cmos_bcd_read(RTC_MONTH, rtc_control); - day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - hr += cmos_bcd_read(RTC_HOURS, rtc_control); - min += cmos_bcd_read(RTC_MINUTES, rtc_control); - sec += cmos_bcd_read(RTC_SECONDS, rtc_control); - } - - spin_unlock_irq(&rtc_lock); - - if (sec > 59) { - min += sec/60; - sec = sec%60; - } - if (min > 59) { - hr += min/60; - min = min%60; - } - if (hr > 23) { - day += hr/24; - hr = hr%24; - } - if (day > 31) { - mo += day/32; - day = day%32; - } - if (mo > 12) { - yr += mo/13; - mo = mo%13; - } - - spin_lock_irq(&rtc_lock); - /* - * Disable alarm interrupt before setting alarm timer or else - * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs - */ - rtc_control &= ~RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - /* write the fields the rtc knows about */ - cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); - cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); - cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); - - /* - * If the system supports an enhanced alarm it will have non-zero - * offsets into the CMOS RAM here -- which for some reason are pointing - * to the RTC area of memory. - */ - if (acpi_gbl_FADT.day_alarm) - cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); - if (acpi_gbl_FADT.month_alarm) - cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); - if (acpi_gbl_FADT.century) { - if (adjust) - yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; - cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); - } - /* enable the rtc alarm interrupt */ - rtc_control |= RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - spin_unlock_irq(&rtc_lock); - - acpi_clear_event(ACPI_EVENT_RTC); - acpi_enable_event(ACPI_EVENT_RTC, 0); - - *ppos += count; - - result = 0; - end: - return result ? result : count; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - static int acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) { @@ -417,41 +145,8 @@ static const struct file_operations acpi_system_wakeup_device_fops = { .release = single_release, }; -#ifdef HAVE_ACPI_LEGACY_ALARM -static const struct file_operations acpi_system_alarm_fops = { - .owner = THIS_MODULE, - .open = acpi_system_alarm_open_fs, - .read = seq_read, - .write = acpi_system_write_alarm, - .llseek = seq_lseek, - .release = single_release, -}; - -static u32 rtc_handler(void *context) -{ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); - - return ACPI_INTERRUPT_HANDLED; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - int __init acpi_sleep_proc_init(void) { -#ifdef HAVE_ACPI_LEGACY_ALARM - /* 'alarm' [R/W] */ - proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_alarm_fops); - - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); - /* - * Disable the RTC event after installing RTC handler. - * Only when RTC alarm is set will it be enabled. - */ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); -#endif /* HAVE_ACPI_LEGACY_ALARM */ - /* 'wakeup device' [R/W] */ proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, acpi_root_dir, &acpi_system_wakeup_device_fops); -- cgit v1.2.3 From d7d49012b917647794b6df33f4e7a61a2c818ccf Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Tue, 15 Oct 2013 19:48:11 +0800 Subject: ACPI / power: Release resource_lock after acpi_power_get_state() return error In acpi_resume_power_resources() resource_lock should be released when acpi_power_get_state() fails and before passing to next power resource on the list. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 0dbe5cdf3396..0c1c3ec784fb 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -936,8 +936,10 @@ void acpi_resume_power_resources(void) mutex_lock(&resource->resource_lock); result = acpi_power_get_state(resource->device.handle, &state); - if (result) + if (result) { + mutex_unlock(&resource->resource_lock); continue; + } if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) { -- cgit v1.2.3 From 7d13f94ce242a9166811eb6a30a5cd712952fb04 Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Sun, 13 Oct 2013 00:11:00 +0200 Subject: ACPI: remove /proc/acpi/event from ACPI_BUTTON help Commit 1696d9d (ACPI: Remove the old /proc/acpi/event interface) left /proc/acpi/event in the ACPI_BUTTON help in Kconfig, so remove it from there. [rjw: Changelog] Signed-off-by: Krzysztof Mazur Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5ea5c32609ac..6efe2ac6902f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -123,9 +123,9 @@ config ACPI_BUTTON default y help This driver handles events on the power, sleep, and lid buttons. - A daemon reads /proc/acpi/event and perform user-defined actions - such as shutting down the system. This is necessary for - software-controlled poweroff. + A daemon reads events from input devices or via netlink and + performs user-defined actions such as shutting down the system. + This is necessary for software-controlled poweroff. To compile this driver as a module, choose M here: the module will be called button. -- cgit v1.2.3 From 67b662e189f469c6d373f81d76b0ef0495940e99 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:44 +0800 Subject: ACPI / video: seperate backlight control and event interface The backlight control and event delivery functionality provided by ACPI video module is mixed together and registered all during video device enumeration time. As a result, the two functionality are also removed together on module unload time or by the acpi_video_unregister function. The two functionalities are actually independent and one may be useful while the other one may be broken, so it is desirable to seperate the two functionalities such that it is clear and easy to disable one functionality without affecting the other one. APIs to selectively remove backlight control interface and/or event delivery functionality can be easily added once needed. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 434 +++++++++++++++++++++++++++++---------------------- 1 file changed, 245 insertions(+), 189 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index aebcf6355df4..3bd1eaa4ef90 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -89,6 +89,8 @@ static bool use_bios_initial_backlight = 1; module_param(use_bios_initial_backlight, bool, 0644); static int register_count; +static struct mutex video_list_lock; +static struct list_head video_bus_head; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); @@ -157,6 +159,7 @@ struct acpi_video_bus { struct acpi_video_bus_flags flags; struct list_head video_device_list; struct mutex device_list_lock; /* protects video_device_list */ + struct list_head entry; struct input_dev *input; char phys[32]; /* for input device */ struct notifier_block pm_nb; @@ -884,79 +887,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (acpi_has_method(device->dev->handle, "_DDC")) device->cap._DDC = 1; - - if (acpi_video_backlight_support()) { - struct backlight_properties props; - struct pci_dev *pdev; - acpi_handle acpi_parent; - struct device *parent = NULL; - int result; - static int count; - char *name; - - result = acpi_video_init_brightness(device); - if (result) - return; - name = kasprintf(GFP_KERNEL, "acpi_video%d", count); - if (!name) - return; - count++; - - acpi_get_parent(device->dev->handle, &acpi_parent); - - pdev = acpi_get_pci_dev(acpi_parent); - if (pdev) { - parent = &pdev->dev; - pci_dev_put(pdev); - } - - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_FIRMWARE; - props.max_brightness = device->brightness->count - 3; - device->backlight = backlight_device_register(name, - parent, - device, - &acpi_backlight_ops, - &props); - kfree(name); - if (IS_ERR(device->backlight)) - return; - - /* - * Save current brightness level in case we have to restore it - * before acpi_video_device_lcd_set_level() is called next time. - */ - device->backlight->props.brightness = - acpi_video_get_brightness(device->backlight); - - device->cooling_dev = thermal_cooling_device_register("LCD", - device->dev, &video_cooling_ops); - if (IS_ERR(device->cooling_dev)) { - /* - * Set cooling_dev to NULL so we don't crash trying to - * free it. - * Also, why the hell we are returning early and - * not attempt to register video output if cooling - * device registration failed? - * -- dtor - */ - device->cooling_dev = NULL; - return; - } - - dev_info(&device->dev->dev, "registered as cooling_device%d\n", - device->cooling_dev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cooling_dev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cooling_dev->device.kobj, - &device->dev->dev.kobj, "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - - } } /* @@ -1143,13 +1073,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, acpi_video_device_bind(video, data); acpi_video_device_find_cap(data); - status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_video_device_notify, data); - if (ACPI_FAILURE(status)) - dev_err(&device->dev, "Error installing notify handler\n"); - else - data->flags.notify = 1; - mutex_lock(&video->device_list_lock); list_add_tail(&data->entry, &video->video_device_list); mutex_unlock(&video->device_list_lock); @@ -1454,64 +1377,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, return status; } -static int acpi_video_bus_put_one_device(struct acpi_video_device *device) -{ - acpi_status status; - - if (!device || !device->video) - return -ENOENT; - - if (device->flags.notify) { - status = acpi_remove_notify_handler(device->dev->handle, - ACPI_DEVICE_NOTIFY, acpi_video_device_notify); - if (ACPI_FAILURE(status)) - dev_err(&device->dev->dev, - "Can't remove video notify handler\n"); - } - - if (device->backlight) { - backlight_device_unregister(device->backlight); - device->backlight = NULL; - } - if (device->cooling_dev) { - sysfs_remove_link(&device->dev->dev.kobj, - "thermal_cooling"); - sysfs_remove_link(&device->cooling_dev->device.kobj, - "device"); - thermal_cooling_device_unregister(device->cooling_dev); - device->cooling_dev = NULL; - } - - return 0; -} - -static int acpi_video_bus_put_devices(struct acpi_video_bus *video) -{ - int status; - struct acpi_video_device *dev, *next; - - mutex_lock(&video->device_list_lock); - - list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { - - status = acpi_video_bus_put_one_device(dev); - if (ACPI_FAILURE(status)) - printk(KERN_WARNING PREFIX - "hhuuhhuu bug in acpi video driver.\n"); - - if (dev->brightness) { - kfree(dev->brightness->levels); - kfree(dev->brightness); - } - list_del(&dev->entry); - kfree(dev); - } - - mutex_unlock(&video->device_list_lock); - - return 0; -} - /* acpi_video interface */ /* @@ -1536,7 +1401,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) struct input_dev *input; int keycode = 0; - if (!video) + if (!video || !video->input) return; input = video->input; @@ -1691,12 +1556,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, return AE_OK; } +static void acpi_video_dev_register_backlight(struct acpi_video_device *device) +{ + if (acpi_video_backlight_support()) { + struct backlight_properties props; + struct pci_dev *pdev; + acpi_handle acpi_parent; + struct device *parent = NULL; + int result; + static int count; + char *name; + + result = acpi_video_init_brightness(device); + if (result) + return; + name = kasprintf(GFP_KERNEL, "acpi_video%d", count); + if (!name) + return; + count++; + + acpi_get_parent(device->dev->handle, &acpi_parent); + + pdev = acpi_get_pci_dev(acpi_parent); + if (pdev) { + parent = &pdev->dev; + pci_dev_put(pdev); + } + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_FIRMWARE; + props.max_brightness = device->brightness->count - 3; + device->backlight = backlight_device_register(name, + parent, + device, + &acpi_backlight_ops, + &props); + kfree(name); + if (IS_ERR(device->backlight)) + return; + + /* + * Save current brightness level in case we have to restore it + * before acpi_video_device_lcd_set_level() is called next time. + */ + device->backlight->props.brightness = + acpi_video_get_brightness(device->backlight); + + device->cooling_dev = thermal_cooling_device_register("LCD", + device->dev, &video_cooling_ops); + if (IS_ERR(device->cooling_dev)) { + /* + * Set cooling_dev to NULL so we don't crash trying to + * free it. + * Also, why the hell we are returning early and + * not attempt to register video output if cooling + * device registration failed? + * -- dtor + */ + device->cooling_dev = NULL; + return; + } + + dev_info(&device->dev->dev, "registered as cooling_device%d\n", + device->cooling_dev->id); + result = sysfs_create_link(&device->dev->dev.kobj, + &device->cooling_dev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&device->cooling_dev->device.kobj, + &device->dev->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + } +} + +static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_register_backlight(dev); + mutex_unlock(&video->device_list_lock); + + video->pm_nb.notifier_call = acpi_video_resume; + video->pm_nb.priority = 0; + return register_pm_notifier(&video->pm_nb); +} + +static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device) +{ + if (device->backlight) { + backlight_device_unregister(device->backlight); + device->backlight = NULL; + } + if (device->brightness) { + kfree(device->brightness->levels); + kfree(device->brightness); + device->brightness = NULL; + } + if (device->cooling_dev) { + sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&device->cooling_dev->device.kobj, "device"); + thermal_cooling_device_unregister(device->cooling_dev); + device->cooling_dev = NULL; + } +} + +static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + int error = unregister_pm_notifier(&video->pm_nb); + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_unregister_backlight(dev); + mutex_unlock(&video->device_list_lock); + + return error; +} + +static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device) +{ + acpi_status status; + struct acpi_device *adev = device->dev; + + status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, + acpi_video_device_notify, device); + if (ACPI_FAILURE(status)) + dev_err(&adev->dev, "Error installing notify handler\n"); + else + device->flags.notify = 1; +} + +static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video) +{ + struct input_dev *input; + struct acpi_video_device *dev; + int error; + + video->input = input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto out; + } + + error = acpi_video_bus_start_devices(video); + if (error) + goto err_free_input; + + snprintf(video->phys, sizeof(video->phys), + "%s/video/input0", acpi_device_hid(video->device)); + + input->name = acpi_device_name(video->device); + input->phys = video->phys; + input->id.bustype = BUS_HOST; + input->id.product = 0x06; + input->dev.parent = &video->device->dev; + input->evbit[0] = BIT(EV_KEY); + set_bit(KEY_SWITCHVIDEOMODE, input->keybit); + set_bit(KEY_VIDEO_NEXT, input->keybit); + set_bit(KEY_VIDEO_PREV, input->keybit); + set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); + set_bit(KEY_BRIGHTNESSUP, input->keybit); + set_bit(KEY_BRIGHTNESSDOWN, input->keybit); + set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); + set_bit(KEY_DISPLAY_OFF, input->keybit); + + error = input_register_device(input); + if (error) + goto err_stop_dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_add_notify_handler(dev); + mutex_unlock(&video->device_list_lock); + + return 0; + +err_stop_dev: + acpi_video_bus_stop_devices(video); +err_free_input: + input_free_device(input); + video->input = NULL; +out: + return error; +} + +static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev) +{ + if (dev->flags.notify) { + acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY, + acpi_video_device_notify); + dev->flags.notify = 0; + } +} + +static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_remove_notify_handler(dev); + mutex_unlock(&video->device_list_lock); + + acpi_video_bus_stop_devices(video); + input_unregister_device(video->input); + video->input = NULL; +} + +static int acpi_video_bus_put_devices(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev, *next; + + mutex_lock(&video->device_list_lock); + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { + list_del(&dev->entry); + kfree(dev); + } + mutex_unlock(&video->device_list_lock); + + return 0; +} + static int instance; static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; - struct input_dev *input; int error; acpi_status status; @@ -1748,62 +1837,24 @@ static int acpi_video_bus_add(struct acpi_device *device) if (error) goto err_put_video; - video->input = input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_put_video; - } - - error = acpi_video_bus_start_devices(video); - if (error) - goto err_free_input_dev; - - snprintf(video->phys, sizeof(video->phys), - "%s/video/input0", acpi_device_hid(video->device)); - - input->name = acpi_device_name(video->device); - input->phys = video->phys; - input->id.bustype = BUS_HOST; - input->id.product = 0x06; - input->dev.parent = &device->dev; - input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_SWITCHVIDEOMODE, input->keybit); - set_bit(KEY_VIDEO_NEXT, input->keybit); - set_bit(KEY_VIDEO_PREV, input->keybit); - set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); - set_bit(KEY_BRIGHTNESSUP, input->keybit); - set_bit(KEY_BRIGHTNESSDOWN, input->keybit); - set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); - set_bit(KEY_DISPLAY_OFF, input->keybit); - printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), video->flags.multihead ? "yes" : "no", video->flags.rom ? "yes" : "no", video->flags.post ? "yes" : "no"); + mutex_lock(&video_list_lock); + list_add_tail(&video->entry, &video_bus_head); + mutex_unlock(&video_list_lock); - video->pm_nb.notifier_call = acpi_video_resume; - video->pm_nb.priority = 0; - error = register_pm_notifier(&video->pm_nb); - if (error) - goto err_stop_video; - - error = input_register_device(input); - if (error) - goto err_unregister_pm_notifier; + acpi_video_bus_register_backlight(video); + acpi_video_bus_add_notify_handler(video); return 0; - err_unregister_pm_notifier: - unregister_pm_notifier(&video->pm_nb); - err_stop_video: - acpi_video_bus_stop_devices(video); - err_free_input_dev: - input_free_device(input); - err_put_video: +err_put_video: acpi_video_bus_put_devices(video); kfree(video->attached_array); - err_free_video: +err_free_video: kfree(video); device->driver_data = NULL; @@ -1820,12 +1871,14 @@ static int acpi_video_bus_remove(struct acpi_device *device) video = acpi_driver_data(device); - unregister_pm_notifier(&video->pm_nb); - - acpi_video_bus_stop_devices(video); + acpi_video_bus_remove_notify_handler(video); + acpi_video_bus_unregister_backlight(video); acpi_video_bus_put_devices(video); - input_unregister_device(video->input); + mutex_lock(&video_list_lock); + list_del(&video->entry); + mutex_unlock(&video_list_lock); + kfree(video->attached_array); kfree(video); @@ -1874,6 +1927,9 @@ int acpi_video_register(void) return 0; } + mutex_init(&video_list_lock); + INIT_LIST_HEAD(&video_bus_head); + result = acpi_bus_register_driver(&acpi_video_bus); if (result < 0) return -ENODEV; -- cgit v1.2.3 From fbc9fe1b4f222a7c575e3bd8e9defe59c6190a04 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:45 +0800 Subject: ACPI / video: Do not register backlight if win8 and native interface exists According to Matthew Garrett, "Windows 8 leaves backlight control up to individual graphics drivers rather than making ACPI calls itself. There's plenty of evidence to suggest that the Intel driver for Windows [8] doesn't use the ACPI interface, including the fact that it's broken on a bunch of machines when the OS claims to support Windows 8. The simplest thing to do appears to be to disable the ACPI backlight interface on these systems". So for Win8 systems, if there is native backlight control interface registered by GPU driver, ACPI video does not need to register its own. Since there are systems that don't work well with this approach, a parameter for video module named use_native_backlight is introduced and has the value of false by default. For users who have a broken ACPI video backlight interface, video.use_native_backlight=1 is needed in kernel cmdline. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/internal.h | 4 +--- drivers/acpi/video.c | 25 ++++++++++++++++++++----- drivers/acpi/video_detect.c | 4 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 20f423337e1f..e9304dc7ebfa 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -169,9 +169,7 @@ int acpi_create_platform_device(struct acpi_device *adev, Video -------------------------------------------------------------------------- */ #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) -bool acpi_video_backlight_quirks(void); -#else -static inline bool acpi_video_backlight_quirks(void) { return false; } +bool acpi_osi_is_win8(void); #endif #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 3bd1eaa4ef90..d020df5a732a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -88,6 +88,13 @@ module_param(allow_duplicates, bool, 0644); static bool use_bios_initial_backlight = 1; module_param(use_bios_initial_backlight, bool, 0644); +/* + * For Windows 8 systems: if set ture and the GPU driver has + * registered a backlight interface, skip registering ACPI video's. + */ +static bool use_native_backlight = false; +module_param(use_native_backlight, bool, 0644); + static int register_count; static struct mutex video_list_lock; static struct list_head video_bus_head; @@ -232,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); +static bool acpi_video_verify_backlight_support(void) +{ + if (acpi_osi_is_win8() && use_native_backlight && + backlight_device_registered(BACKLIGHT_RAW)) + return false; + return acpi_video_backlight_support(); +} + /* backlight device sysfs support */ static int acpi_video_get_brightness(struct backlight_device *bd) { @@ -1256,8 +1271,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; - /* no warning message if acpi_backlight=vendor is used */ - if (!acpi_video_backlight_support()) + /* no warning message if acpi_backlight=vendor or a quirk is used */ + if (!acpi_video_verify_backlight_support()) return 0; if (!device->brightness) @@ -1386,13 +1401,13 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { return acpi_video_bus_DOS(video, 0, - acpi_video_backlight_quirks() ? 1 : 0); + acpi_osi_is_win8() ? 1 : 0); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) { return acpi_video_bus_DOS(video, 0, - acpi_video_backlight_quirks() ? 0 : 1); + acpi_osi_is_win8() ? 0 : 1); } static void acpi_video_bus_notify(struct acpi_device *device, u32 event) @@ -1558,7 +1573,7 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, static void acpi_video_dev_register_backlight(struct acpi_video_device *device) { - if (acpi_video_backlight_support()) { + if (acpi_video_verify_backlight_support()) { struct backlight_properties props; struct pci_dev *pdev; acpi_handle acpi_parent; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 940edbf2fe8f..b6399343de51 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -233,11 +233,11 @@ static void acpi_video_caps_check(void) acpi_video_get_capabilities(NULL); } -bool acpi_video_backlight_quirks(void) +bool acpi_osi_is_win8(void) { return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; } -EXPORT_SYMBOL(acpi_video_backlight_quirks); +EXPORT_SYMBOL(acpi_osi_is_win8); /* Promote the vendor interface instead of the generic video module. * This function allow DMI blacklists to be implemented by externals -- cgit v1.2.3 From ab0fd674d6cef0904baa511f22613ef6474f8169 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Sat, 12 Oct 2013 21:04:48 +0800 Subject: ACPI / AC: Remove AC's proc directory. AC's proc directory is not used and so remove it. Prepare for removing /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 129 ++---------------------------------------------------- 1 file changed, 3 insertions(+), 126 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 324b5a096eff..b9f0d5f4bba5 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -30,10 +30,6 @@ #include #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#endif #include #include #include @@ -56,12 +52,6 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); -#ifdef CONFIG_ACPI_PROCFS_POWER -extern struct proc_dir_entry *acpi_lock_ac_dir(void); -extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); -static int acpi_ac_open_fs(struct inode *inode, struct file *file); -#endif - static int ac_sleep_before_get_state_ms; struct acpi_ac { @@ -73,16 +63,6 @@ struct acpi_ac { #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) -#ifdef CONFIG_ACPI_PROCFS_POWER -static const struct file_operations acpi_ac_fops = { - .owner = THIS_MODULE, - .open = acpi_ac_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - /* -------------------------------------------------------------------------- AC Adapter Management -------------------------------------------------------------------------- */ @@ -132,83 +112,6 @@ static enum power_supply_property ac_props[] = { POWER_SUPPLY_PROP_ONLINE, }; -#ifdef CONFIG_ACPI_PROCFS_POWER -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -static struct proc_dir_entry *acpi_ac_dir; - -static int acpi_ac_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_ac *ac = seq->private; - - - if (!ac) - return 0; - - if (acpi_ac_get_state(ac)) { - seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); - return 0; - } - - seq_puts(seq, "state: "); - switch (ac->state) { - case ACPI_AC_STATUS_OFFLINE: - seq_puts(seq, "off-line\n"); - break; - case ACPI_AC_STATUS_ONLINE: - seq_puts(seq, "on-line\n"); - break; - default: - seq_puts(seq, "unknown\n"); - break; - } - - return 0; -} - -static int acpi_ac_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); -} - -static int acpi_ac_add_fs(struct acpi_ac *ac) -{ - struct proc_dir_entry *entry = NULL; - - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(ac->adev)) { - acpi_device_dir(ac->adev) = - proc_mkdir(acpi_device_bid(ac->adev), acpi_ac_dir); - if (!acpi_device_dir(ac->adev)) - return -ENODEV; - } - - /* 'state' [R] */ - entry = proc_create_data(ACPI_AC_FILE_STATE, - S_IRUGO, acpi_device_dir(ac->adev), - &acpi_ac_fops, ac); - if (!entry) - return -ENODEV; - return 0; -} - -static int acpi_ac_remove_fs(struct acpi_ac *ac) -{ - - if (acpi_device_dir(ac->adev)) { - remove_proc_entry(ACPI_AC_FILE_STATE, - acpi_device_dir(ac->adev)); - remove_proc_entry(acpi_device_bid(ac->adev), acpi_ac_dir); - acpi_device_dir(ac->adev) = NULL; - } - - return 0; -} -#endif - /* -------------------------------------------------------------------------- Driver Model -------------------------------------------------------------------------- */ @@ -293,11 +196,6 @@ static int acpi_ac_probe(struct platform_device *pdev) if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_ac_add_fs(ac); - if (result) - goto end; -#endif ac->charger.name = acpi_device_bid(adev); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; @@ -317,13 +215,9 @@ static int acpi_ac_probe(struct platform_device *pdev) acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); - end: - if (result) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(ac); -#endif +end: + if (result) kfree(ac); - } dmi_check_system(ac_dmi_table); return result; @@ -366,10 +260,6 @@ static int acpi_ac_remove(struct platform_device *pdev) if (ac->charger.dev) power_supply_unregister(&ac->charger); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(ac); -#endif - kfree(ac); return 0; @@ -399,19 +289,9 @@ static int __init acpi_ac_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) - return -ENODEV; -#endif - result = platform_driver_register(&acpi_ac_driver); - if (result < 0) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_ac_dir(acpi_ac_dir); -#endif + if (result < 0) return -ENODEV; - } return 0; } @@ -419,9 +299,6 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { platform_driver_unregister(&acpi_ac_driver); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_ac_dir(acpi_ac_dir); -#endif } module_init(acpi_ac_init); module_exit(acpi_ac_exit); -- cgit v1.2.3 From a8d52f4495f21da3f47f7318301abf6823ec6648 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Oct 2013 02:55:05 +0200 Subject: ACPI / video: Add Lenovo IdeaPad Yoga 13 to acpi video detect blacklist On the Yoga 13 the backlight control doesn't work via ACPI. (And doesn't work either with the low-level platform driver ideapad_laptop; but works correctly via the intel video driver). This patch hence adds the Yoga 13 to the ACPI video detect blacklist, to make sure the broken ACPI backlight device is never exposed to userspace. Note that this appears unrelated to the Windows 8 backlight issues tracked here: https://bugzilla.kernel.org/show_bug.cgi?id=51231 https://bugzilla.kernel.org/show_bug.cgi?id=60682 The Yoga's ACPI backlight controls work neither with nor without acpi_osi="!Windows 2012" on the kernel command line. It appears that backlight control via the EC simply is not available at all, regardless whether done via ACPI or via the vendor driver. Signed-off-by: Lennart Poettering Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b6399343de51..84875fd4c74f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -168,6 +168,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, + { + .callback = video_detect_force_vendor, + .ident = "Lenovo Yoga 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), + }, + }, { }, }; -- cgit v1.2.3 From 9208e3110bf0a6ba4ded56e374857d4b6609c911 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 16 Oct 2013 13:15:14 +0300 Subject: ACPI / platform: add ACPI ID for a Broadcom GPS chip This adds ACPI ID for Broadcom GPS receiver BCM4752. Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_platform.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index aef79db906fe..8a4cfc7e71f0 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -31,6 +31,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, { "ACPI0003" }, { "VPC2004" }, + { "BCM4752" }, /* Intel Smart Sound Technology */ { "INT33C8" }, -- cgit v1.2.3 From 41863fcee3039ec3de15003b78e7284c4393e862 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 16 Oct 2013 23:05:42 +0200 Subject: ACPI / power: Drop automaitc resume of power resource dependent devices The mechanism causing devices depending on a given power resource (that is, devices that can be in D0 only if that power resource is on) to be resumed automatically when the power resource is turned on (and their "inferred" power state becomes D0 as a result) is inherently racy and in fact unnecessary. It is racy, because if the power resource is turned on and then immediately off, the device resume triggered by the first transition to "on" may still happen, causing the power resource to be turned on again. That again will trigger the "resume of dependent devices" mechanism, but if the devices in question are not in use, they will be suspended in the meantime causing the power resource to be turned off. However, the "resume of dependent devices" will next resume them again and so on. In some cases (USB port PM in particular) that leads to an endless busy loop of flipping the resource on and off continuously. It is needless, because whoever turns a power resource on will most likely turn it off at some point and the devices that go into "D0" as a result of turning it on will then go back into D3cold (generally, the state they were in before). Moreover, turning on all power resources a device needs to go into D0 is not sufficient for a full transition into D0 in general. Namely, _PS0 may need to be executed in addition to that in some cases. This means that the whole rationale of the "resume of dependent devices" mechanism was incorrect to begin with and it's best to remove it entirely. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 100 +-------------------------------------------------- 1 file changed, 1 insertion(+), 99 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 0c1c3ec784fb..c2ad391d8041 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -59,16 +59,9 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -struct acpi_power_dependent_device { - struct list_head node; - struct acpi_device *adev; - struct work_struct work; -}; - struct acpi_power_resource { struct acpi_device device; struct list_head list_node; - struct list_head dependent; char *name; u32 system_level; u32 order; @@ -233,32 +226,6 @@ static int acpi_power_get_list_state(struct list_head *list, int *state) return 0; } -static void acpi_power_resume_dependent(struct work_struct *work) -{ - struct acpi_power_dependent_device *dep; - struct acpi_device_physical_node *pn; - struct acpi_device *adev; - int state; - - dep = container_of(work, struct acpi_power_dependent_device, work); - adev = dep->adev; - if (acpi_power_get_inferred_state(adev, &state)) - return; - - if (state > ACPI_STATE_D0) - return; - - mutex_lock(&adev->physical_node_lock); - - list_for_each_entry(pn, &adev->physical_node_list, node) - pm_request_resume(pn->dev); - - list_for_each_entry(pn, &adev->power_dependent, node) - pm_request_resume(pn->dev); - - mutex_unlock(&adev->physical_node_lock); -} - static int __acpi_power_on(struct acpi_power_resource *resource) { acpi_status status = AE_OK; @@ -283,14 +250,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource) resource->name)); } else { result = __acpi_power_on(resource); - if (result) { + if (result) resource->ref_count--; - } else { - struct acpi_power_dependent_device *dep; - - list_for_each_entry(dep, &resource->dependent, node) - schedule_work(&dep->work); - } } return result; } @@ -390,52 +351,6 @@ static int acpi_power_on_list(struct list_head *list) return result; } -static void acpi_power_add_dependent(struct acpi_power_resource *resource, - struct acpi_device *adev) -{ - struct acpi_power_dependent_device *dep; - - mutex_lock(&resource->resource_lock); - - list_for_each_entry(dep, &resource->dependent, node) - if (dep->adev == adev) - goto out; - - dep = kzalloc(sizeof(*dep), GFP_KERNEL); - if (!dep) - goto out; - - dep->adev = adev; - INIT_WORK(&dep->work, acpi_power_resume_dependent); - list_add_tail(&dep->node, &resource->dependent); - - out: - mutex_unlock(&resource->resource_lock); -} - -static void acpi_power_remove_dependent(struct acpi_power_resource *resource, - struct acpi_device *adev) -{ - struct acpi_power_dependent_device *dep; - struct work_struct *work = NULL; - - mutex_lock(&resource->resource_lock); - - list_for_each_entry(dep, &resource->dependent, node) - if (dep->adev == adev) { - list_del(&dep->node); - work = &dep->work; - break; - } - - mutex_unlock(&resource->resource_lock); - - if (work) { - cancel_work_sync(work); - kfree(dep); - } -} - static struct attribute *attrs[] = { NULL, }; @@ -524,8 +439,6 @@ static void acpi_power_expose_hide(struct acpi_device *adev, void acpi_power_add_remove_device(struct acpi_device *adev, bool add) { - struct acpi_device_power_state *ps; - struct acpi_power_resource_entry *entry; int state; if (adev->wakeup.flags.valid) @@ -535,16 +448,6 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add) if (!adev->power.flags.power_resources) return; - ps = &adev->power.states[ACPI_STATE_D0]; - list_for_each_entry(entry, &ps->resources, node) { - struct acpi_power_resource *resource = entry->resource; - - if (add) - acpi_power_add_dependent(resource, adev); - else - acpi_power_remove_dependent(resource, adev); - } - for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) acpi_power_expose_hide(adev, &adev->power.states[state].resources, @@ -882,7 +785,6 @@ int acpi_add_power_resource(acpi_handle handle) acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER, ACPI_STA_DEFAULT); mutex_init(&resource->resource_lock); - INIT_LIST_HEAD(&resource->dependent); INIT_LIST_HEAD(&resource->list_node); resource->name = device->pnp.bus_id; strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); -- cgit v1.2.3 From 2421ad48f4aed63bc890e8f3c53ed581a542fb66 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 17 Oct 2013 15:44:48 +0200 Subject: ACPI / PM: Drop two functions that are not used any more Two functions defined in device_pm.c, acpi_dev_pm_add_dependent() and acpi_dev_pm_remove_dependent(), have no callers and may be dropped, so drop them. Moreover, they are the only functions adding entries to and removing entries from the power_dependent list in struct acpi_device, so drop that list too. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 56 ------------------------------------------------ drivers/acpi/scan.c | 1 - 2 files changed, 57 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 59d3202f6b36..a94383d1f350 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1025,60 +1025,4 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) } } EXPORT_SYMBOL_GPL(acpi_dev_pm_detach); - -/** - * acpi_dev_pm_add_dependent - Add physical device depending for PM. - * @handle: Handle of ACPI device node. - * @depdev: Device depending on that node for PM. - */ -void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev) -{ - struct acpi_device_physical_node *dep; - struct acpi_device *adev; - - if (!depdev || acpi_bus_get_device(handle, &adev)) - return; - - mutex_lock(&adev->physical_node_lock); - - list_for_each_entry(dep, &adev->power_dependent, node) - if (dep->dev == depdev) - goto out; - - dep = kzalloc(sizeof(*dep), GFP_KERNEL); - if (dep) { - dep->dev = depdev; - list_add_tail(&dep->node, &adev->power_dependent); - } - - out: - mutex_unlock(&adev->physical_node_lock); -} -EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent); - -/** - * acpi_dev_pm_remove_dependent - Remove physical device depending for PM. - * @handle: Handle of ACPI device node. - * @depdev: Device depending on that node for PM. - */ -void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev) -{ - struct acpi_device_physical_node *dep; - struct acpi_device *adev; - - if (!depdev || acpi_bus_get_device(handle, &adev)) - return; - - mutex_lock(&adev->physical_node_lock); - - list_for_each_entry(dep, &adev->power_dependent, node) - if (dep->dev == depdev) { - list_del(&dep->node); - kfree(dep); - break; - } - - mutex_unlock(&adev->physical_node_lock); -} -EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent); #endif /* CONFIG_PM */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 407ad13cac2f..fee8a297c7d9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -999,7 +999,6 @@ int acpi_device_add(struct acpi_device *device, INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); mutex_init(&device->physical_node_lock); - INIT_LIST_HEAD(&device->power_dependent); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); if (!new_bus_id) { -- cgit v1.2.3 From 5e2be4e0edff4a1021b6743ca6859129cd8e7067 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Oct 2013 12:01:43 +0300 Subject: ACPI / osl: remove an unneeded NULL check "str" is never NULL here so I have removed the check. There are static checkers which complain about superfluous NULL checks because it may indicate confusion or a bug. Signed-off-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b1629b571cb2..4923dd4232b3 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1335,7 +1335,7 @@ static int __init acpi_os_name_setup(char *str) if (!str || !*str) return 0; - for (; count-- && str && *str; str++) { + for (; count-- && *str; str++) { if (isalnum(*str) || *str == ' ' || *str == ':') *p++ = *str; else if (*str == '\'' || *str == '"') -- cgit v1.2.3 From 833ba4b1ba653f279c78e8e3352527acce8946e6 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 18 Oct 2013 14:27:51 -0700 Subject: ACPI, APEI, CPER: Fix status check during error printing Commit aaf9d93be71c: ACPI / APEI: fix error status check condition for CPER only catches condition check before print, but a similar check is needed during printing CPER error sections. Signed-off-by: Chen, Gong Reviewed-by: Borislav Petkov Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Tony Luck --- drivers/acpi/apei/cper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index 33dc6a004802..f827f02bfbe8 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -353,7 +353,7 @@ void apei_estatus_print(const char *pfx, cper_severity_str(severity)); data_len = estatus->data_length; gdata = (struct acpi_hest_generic_data *)(estatus + 1); - while (data_len > sizeof(*gdata)) { + while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; apei_estatus_print_section(pfx, gdata, sec_no); data_len -= gedata_len + sizeof(*gdata); -- cgit v1.2.3 From 88f074f4871a8c212b212b725e4dcdcdb09613c1 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 18 Oct 2013 14:28:59 -0700 Subject: ACPI, CPER: Update cper info We have a lot of confusing names of functions and data structures in amongs the the error reporting code. In particular the "apei" prefix has been applied to many objects that are not part of APEI. Since we will be using these routines for extended error log reporting it will be clearer if we fix up the names first. Signed-off-by: Chen, Gong Acked-by: Borislav Petkov Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Tony Luck --- drivers/acpi/apei/apei-internal.h | 12 ++++---- drivers/acpi/apei/cper.c | 58 +++++++++++++++++++-------------------- drivers/acpi/apei/ghes.c | 54 ++++++++++++++++++------------------ 3 files changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index f220d642136e..21ba34a73883 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -122,11 +122,11 @@ struct dentry; struct dentry *apei_get_debugfs_dir(void); #define apei_estatus_for_each_section(estatus, section) \ - for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ + for (section = (struct acpi_generic_data *)(estatus + 1); \ (void *)section - (void *)estatus < estatus->data_length; \ section = (void *)(section+1) + section->error_data_length) -static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus) +static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) { if (estatus->raw_data_length) return estatus->raw_data_offset + \ @@ -135,10 +135,10 @@ static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus) return sizeof(*estatus) + estatus->data_length; } -void apei_estatus_print(const char *pfx, - const struct acpi_hest_generic_status *estatus); -int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus); -int apei_estatus_check(const struct acpi_hest_generic_status *estatus); +void cper_estatus_print(const char *pfx, + const struct acpi_generic_status *estatus); +int cper_estatus_check_header(const struct acpi_generic_status *estatus); +int cper_estatus_check(const struct acpi_generic_status *estatus); int apei_osc_setup(void); #endif diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index f827f02bfbe8..eb5f6d6d7dbc 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -5,7 +5,7 @@ * Author: Huang Ying * * CPER is the format used to describe platform hardware error by - * various APEI tables, such as ERST, BERT and HEST etc. + * various tables, such as ERST, BERT and HEST etc. * * For more information about CPER, please refer to Appendix N of UEFI * Specification version 2.3. @@ -73,7 +73,7 @@ static const char *cper_severity_str(unsigned int severity) * printed, with @pfx is printed at the beginning of each line. */ void cper_print_bits(const char *pfx, unsigned int bits, - const char *strs[], unsigned int strs_size) + const char * const strs[], unsigned int strs_size) { int i, len = 0; const char *str; @@ -98,32 +98,32 @@ void cper_print_bits(const char *pfx, unsigned int bits, printk("%s\n", buf); } -static const char *cper_proc_type_strs[] = { +static const char * const cper_proc_type_strs[] = { "IA32/X64", "IA64", }; -static const char *cper_proc_isa_strs[] = { +static const char * const cper_proc_isa_strs[] = { "IA32", "IA64", "X64", }; -static const char *cper_proc_error_type_strs[] = { +static const char * const cper_proc_error_type_strs[] = { "cache error", "TLB error", "bus error", "micro-architectural error", }; -static const char *cper_proc_op_strs[] = { +static const char * const cper_proc_op_strs[] = { "unknown or generic", "data read", "data write", "instruction execution", }; -static const char *cper_proc_flag_strs[] = { +static const char * const cper_proc_flag_strs[] = { "restartable", "precise IP", "overflow", @@ -248,7 +248,7 @@ static const char *cper_pcie_port_type_strs[] = { }; static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, - const struct acpi_hest_generic_data *gdata) + const struct acpi_generic_data *gdata) { if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, @@ -283,17 +283,17 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, pfx, pcie->bridge.secondary_status, pcie->bridge.control); } -static const char *apei_estatus_section_flag_strs[] = { +static const char * const cper_estatus_section_flag_strs[] = { "primary", "containment warning", "reset", - "threshold exceeded", + "error threshold exceeded", "resource not accessible", "latent error", }; -static void apei_estatus_print_section( - const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no) +static void cper_estatus_print_section( + const char *pfx, const struct acpi_generic_data *gdata, int sec_no) { uuid_le *sec_type = (uuid_le *)gdata->section_type; __u16 severity; @@ -302,8 +302,8 @@ static void apei_estatus_print_section( printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity, cper_severity_str(severity)); printk("%s""flags: 0x%02x\n", pfx, gdata->flags); - cper_print_bits(pfx, gdata->flags, apei_estatus_section_flag_strs, - ARRAY_SIZE(apei_estatus_section_flag_strs)); + cper_print_bits(pfx, gdata->flags, cper_estatus_section_flag_strs, + ARRAY_SIZE(cper_estatus_section_flag_strs)); if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) @@ -339,34 +339,34 @@ err_section_too_small: pr_err(FW_WARN "error section length is too small\n"); } -void apei_estatus_print(const char *pfx, - const struct acpi_hest_generic_status *estatus) +void cper_estatus_print(const char *pfx, + const struct acpi_generic_status *estatus) { - struct acpi_hest_generic_data *gdata; + struct acpi_generic_data *gdata; unsigned int data_len, gedata_len; int sec_no = 0; __u16 severity; - printk("%s""APEI generic hardware error status\n", pfx); + printk("%s""Generic Hardware Error Status\n", pfx); severity = estatus->error_severity; printk("%s""severity: %d, %s\n", pfx, severity, cper_severity_str(severity)); data_len = estatus->data_length; - gdata = (struct acpi_hest_generic_data *)(estatus + 1); + gdata = (struct acpi_generic_data *)(estatus + 1); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; - apei_estatus_print_section(pfx, gdata, sec_no); + cper_estatus_print_section(pfx, gdata, sec_no); data_len -= gedata_len + sizeof(*gdata); gdata = (void *)(gdata + 1) + gedata_len; sec_no++; } } -EXPORT_SYMBOL_GPL(apei_estatus_print); +EXPORT_SYMBOL_GPL(cper_estatus_print); -int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) +int cper_estatus_check_header(const struct acpi_generic_status *estatus) { if (estatus->data_length && - estatus->data_length < sizeof(struct acpi_hest_generic_data)) + estatus->data_length < sizeof(struct acpi_generic_data)) return -EINVAL; if (estatus->raw_data_length && estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) @@ -374,19 +374,19 @@ int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) return 0; } -EXPORT_SYMBOL_GPL(apei_estatus_check_header); +EXPORT_SYMBOL_GPL(cper_estatus_check_header); -int apei_estatus_check(const struct acpi_hest_generic_status *estatus) +int cper_estatus_check(const struct acpi_generic_status *estatus) { - struct acpi_hest_generic_data *gdata; + struct acpi_generic_data *gdata; unsigned int data_len, gedata_len; int rc; - rc = apei_estatus_check_header(estatus); + rc = cper_estatus_check_header(estatus); if (rc) return rc; data_len = estatus->data_length; - gdata = (struct acpi_hest_generic_data *)(estatus + 1); + gdata = (struct acpi_generic_data *)(estatus + 1); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; if (gedata_len > data_len - sizeof(*gdata)) @@ -399,4 +399,4 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus) return 0; } -EXPORT_SYMBOL_GPL(apei_estatus_check); +EXPORT_SYMBOL_GPL(cper_estatus_check); diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 8ec37bbdd699..0db6e4ff6501 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -75,13 +75,13 @@ #define GHES_ESTATUS_CACHE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_cache) + (estatus_len)) #define GHES_ESTATUS_FROM_CACHE(estatus_cache) \ - ((struct acpi_hest_generic_status *) \ + ((struct acpi_generic_status *) \ ((struct ghes_estatus_cache *)(estatus_cache) + 1)) #define GHES_ESTATUS_NODE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_node) + (estatus_len)) -#define GHES_ESTATUS_FROM_NODE(estatus_node) \ - ((struct acpi_hest_generic_status *) \ +#define GHES_ESTATUS_FROM_NODE(estatus_node) \ + ((struct acpi_generic_status *) \ ((struct ghes_estatus_node *)(estatus_node) + 1)) bool ghes_disable; @@ -378,17 +378,17 @@ static int ghes_read_estatus(struct ghes *ghes, int silent) ghes->flags |= GHES_TO_CLEAR; rc = -EIO; - len = apei_estatus_len(ghes->estatus); + len = cper_estatus_len(ghes->estatus); if (len < sizeof(*ghes->estatus)) goto err_read_block; if (len > ghes->generic->error_block_length) goto err_read_block; - if (apei_estatus_check_header(ghes->estatus)) + if (cper_estatus_check_header(ghes->estatus)) goto err_read_block; ghes_copy_tofrom_phys(ghes->estatus + 1, buf_paddr + sizeof(*ghes->estatus), len - sizeof(*ghes->estatus), 1); - if (apei_estatus_check(ghes->estatus)) + if (cper_estatus_check(ghes->estatus)) goto err_read_block; rc = 0; @@ -409,7 +409,7 @@ static void ghes_clear_estatus(struct ghes *ghes) ghes->flags &= ~GHES_TO_CLEAR; } -static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) +static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) { #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE unsigned long pfn; @@ -438,10 +438,10 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int } static void ghes_do_proc(struct ghes *ghes, - const struct acpi_hest_generic_status *estatus) + const struct acpi_generic_status *estatus) { int sev, sec_sev; - struct acpi_hest_generic_data *gdata; + struct acpi_generic_data *gdata; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { @@ -496,7 +496,7 @@ static void ghes_do_proc(struct ghes *ghes, static void __ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_hest_generic_status *estatus) + const struct acpi_generic_status *estatus) { static atomic_t seqno; unsigned int curr_seqno; @@ -513,12 +513,12 @@ static void __ghes_print_estatus(const char *pfx, snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}" HW_ERR, pfx, curr_seqno); printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n", pfx_seq, generic->header.source_id); - apei_estatus_print(pfx_seq, estatus); + cper_estatus_print(pfx_seq, estatus); } static int ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_hest_generic_status *estatus) + const struct acpi_generic_status *estatus) { /* Not more than 2 messages every 5 seconds */ static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); @@ -540,15 +540,15 @@ static int ghes_print_estatus(const char *pfx, * GHES error status reporting throttle, to report more kinds of * errors, instead of just most frequently occurred errors. */ -static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus) +static int ghes_estatus_cached(struct acpi_generic_status *estatus) { u32 len; int i, cached = 0; unsigned long long now; struct ghes_estatus_cache *cache; - struct acpi_hest_generic_status *cache_estatus; + struct acpi_generic_status *cache_estatus; - len = apei_estatus_len(estatus); + len = cper_estatus_len(estatus); rcu_read_lock(); for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) { cache = rcu_dereference(ghes_estatus_caches[i]); @@ -571,19 +571,19 @@ static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus) static struct ghes_estatus_cache *ghes_estatus_cache_alloc( struct acpi_hest_generic *generic, - struct acpi_hest_generic_status *estatus) + struct acpi_generic_status *estatus) { int alloced; u32 len, cache_len; struct ghes_estatus_cache *cache; - struct acpi_hest_generic_status *cache_estatus; + struct acpi_generic_status *cache_estatus; alloced = atomic_add_return(1, &ghes_estatus_cache_alloced); if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) { atomic_dec(&ghes_estatus_cache_alloced); return NULL; } - len = apei_estatus_len(estatus); + len = cper_estatus_len(estatus); cache_len = GHES_ESTATUS_CACHE_LEN(len); cache = (void *)gen_pool_alloc(ghes_estatus_pool, cache_len); if (!cache) { @@ -603,7 +603,7 @@ static void ghes_estatus_cache_free(struct ghes_estatus_cache *cache) { u32 len; - len = apei_estatus_len(GHES_ESTATUS_FROM_CACHE(cache)); + len = cper_estatus_len(GHES_ESTATUS_FROM_CACHE(cache)); len = GHES_ESTATUS_CACHE_LEN(len); gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len); atomic_dec(&ghes_estatus_cache_alloced); @@ -619,7 +619,7 @@ static void ghes_estatus_cache_rcu_free(struct rcu_head *head) static void ghes_estatus_cache_add( struct acpi_hest_generic *generic, - struct acpi_hest_generic_status *estatus) + struct acpi_generic_status *estatus) { int i, slot = -1, count; unsigned long long now, duration, period, max_period = 0; @@ -751,7 +751,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) struct llist_node *llnode, *next; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_hest_generic_status *estatus; + struct acpi_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -765,7 +765,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) estatus_node = llist_entry(llnode, struct ghes_estatus_node, llnode); estatus = GHES_ESTATUS_FROM_NODE(estatus_node); - len = apei_estatus_len(estatus); + len = cper_estatus_len(estatus); node_len = GHES_ESTATUS_NODE_LEN(len); ghes_do_proc(estatus_node->ghes, estatus); if (!ghes_estatus_cached(estatus)) { @@ -784,7 +784,7 @@ static void ghes_print_queued_estatus(void) struct llist_node *llnode; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_hest_generic_status *estatus; + struct acpi_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -797,7 +797,7 @@ static void ghes_print_queued_estatus(void) estatus_node = llist_entry(llnode, struct ghes_estatus_node, llnode); estatus = GHES_ESTATUS_FROM_NODE(estatus_node); - len = apei_estatus_len(estatus); + len = cper_estatus_len(estatus); node_len = GHES_ESTATUS_NODE_LEN(len); generic = estatus_node->generic; ghes_print_estatus(NULL, generic, estatus); @@ -843,7 +843,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG u32 len, node_len; struct ghes_estatus_node *estatus_node; - struct acpi_hest_generic_status *estatus; + struct acpi_generic_status *estatus; #endif if (!(ghes->flags & GHES_TO_CLEAR)) continue; @@ -851,7 +851,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) if (ghes_estatus_cached(ghes->estatus)) goto next; /* Save estatus for further processing in IRQ context */ - len = apei_estatus_len(ghes->estatus); + len = cper_estatus_len(ghes->estatus); node_len = GHES_ESTATUS_NODE_LEN(len); estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool, node_len); @@ -923,7 +923,7 @@ static int ghes_probe(struct platform_device *ghes_dev) rc = -EIO; if (generic->error_block_length < - sizeof(struct acpi_hest_generic_status)) { + sizeof(struct acpi_generic_status)) { pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", generic->error_block_length, generic->header.source_id); -- cgit v1.2.3 From 4b3db708b114fc35ff1e0cd28a2bfb1490dbb5d3 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Mon, 21 Oct 2013 14:29:25 -0700 Subject: ACPI, x86: Extended error log driver for x86 platform This H/W error log driver (a.k.a eMCA driver) is implemented based on http://www.intel.com/content/www/us/en/architecture-and-technology/enhanced-mca-logging-xeon-paper.html After errors are captured, more detailed platform specific information can be got via this new enhanced H/W error log driver. Most notably we can track memory errors back to the DIMM slot silk screen label. Signed-off-by: Chen, Gong Signed-off-by: Tony Luck --- drivers/acpi/Kconfig | 19 +++ drivers/acpi/Makefile | 2 + drivers/acpi/acpi_extlog.c | 327 +++++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/bus.c | 3 +- 4 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/acpi_extlog.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 6efe2ac6902f..252f0e818a49 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -372,4 +372,23 @@ config ACPI_BGRT source "drivers/acpi/apei/Kconfig" +config ACPI_EXTLOG + tristate "Extended Error Log support" + depends on X86_MCE && ACPI_APEI + default n + help + Certain usages such as Predictive Failure Analysis (PFA) require + more information about the error than what can be described in + processor machine check banks. Most server processors log + additional information about the error in processor uncore + registers. Since the addresses and layout of these registers vary + widely from one processor to another, system software cannot + readily make use of them. To complicate matters further, some of + the additional error information cannot be constructed without + detailed knowledge about platform topology. + + Enhanced MCA Logging allows firmware to provide additional error + information to system software, synchronous with MCE or CMCI. This + driver adds support for that functionality. + endif # ACPI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index cdaf68b58b00..bce34afadcd0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -82,3 +82,5 @@ processor-$(CONFIG_CPU_FREQ) += processor_perflib.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o obj-$(CONFIG_ACPI_APEI) += apei/ + +obj-$(CONFIG_ACPI_EXTLOG) += acpi_extlog.o diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c new file mode 100644 index 000000000000..a6869e110ce5 --- /dev/null +++ b/drivers/acpi/acpi_extlog.c @@ -0,0 +1,327 @@ +/* + * Extended Error Log driver + * + * Copyright (C) 2013 Intel Corp. + * Author: Chen, Gong + * + * This file is licensed under GPLv2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "apei/apei-internal.h" + +#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ + +#define EXTLOG_DSM_REV 0x0 +#define EXTLOG_FN_QUERY 0x0 +#define EXTLOG_FN_ADDR 0x1 + +#define FLAG_OS_OPTIN BIT(0) +#define EXTLOG_QUERY_L1_EXIST BIT(1) +#define ELOG_ENTRY_VALID (1ULL<<63) +#define ELOG_ENTRY_LEN 0x1000 + +#define EMCA_BUG \ + "Can not request iomem region <0x%016llx-0x%016llx> - eMCA disabled\n" + +struct extlog_l1_head { + u32 ver; /* Header Version */ + u32 hdr_len; /* Header Length */ + u64 total_len; /* entire L1 Directory length including this header */ + u64 elog_base; /* MCA Error Log Directory base address */ + u64 elog_len; /* MCA Error Log Directory length */ + u32 flags; /* bit 0 - OS/VMM Opt-in */ + u8 rev0[12]; + u32 entries; /* Valid L1 Directory entries per logical processor */ + u8 rev1[12]; +}; + +static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; + +/* L1 table related physical address */ +static u64 elog_base; +static size_t elog_size; +static u64 l1_dirbase; +static size_t l1_size; + +/* L1 table related virtual address */ +static void __iomem *extlog_l1_addr; +static void __iomem *elog_addr; + +static void *elog_buf; + +static u64 *l1_entry_base; +static u32 l1_percpu_entry; + +#define ELOG_IDX(cpu, bank) \ + (cpu_physical_id(cpu) * l1_percpu_entry + (bank)) + +#define ELOG_ENTRY_DATA(idx) \ + (*(l1_entry_base + (idx))) + +#define ELOG_ENTRY_ADDR(phyaddr) \ + (phyaddr - elog_base + (u8 *)elog_addr) + +static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) +{ + int idx; + u64 data; + struct acpi_generic_status *estatus; + + WARN_ON(cpu < 0); + idx = ELOG_IDX(cpu, bank); + data = ELOG_ENTRY_DATA(idx); + if ((data & ELOG_ENTRY_VALID) == 0) + return NULL; + + data &= EXT_ELOG_ENTRY_MASK; + estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data); + + /* if no valid data in elog entry, just return */ + if (estatus->block_status == 0) + return NULL; + + return estatus; +} + +static void __print_extlog_rcd(const char *pfx, + struct acpi_generic_status *estatus, int cpu) +{ + static atomic_t seqno; + unsigned int curr_seqno; + char pfx_seq[64]; + + if (!pfx) { + if (estatus->error_severity <= CPER_SEV_CORRECTED) + pfx = KERN_INFO; + else + pfx = KERN_ERR; + } + curr_seqno = atomic_inc_return(&seqno); + snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}", pfx, curr_seqno); + printk("%s""Hardware error detected on CPU%d\n", pfx_seq, cpu); + cper_estatus_print(pfx_seq, estatus); +} + +static int print_extlog_rcd(const char *pfx, + struct acpi_generic_status *estatus, int cpu) +{ + /* Not more than 2 messages every 5 seconds */ + static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); + static DEFINE_RATELIMIT_STATE(ratelimit_uncorrected, 5*HZ, 2); + struct ratelimit_state *ratelimit; + + if (estatus->error_severity == CPER_SEV_CORRECTED || + (estatus->error_severity == CPER_SEV_INFORMATIONAL)) + ratelimit = &ratelimit_corrected; + else + ratelimit = &ratelimit_uncorrected; + if (__ratelimit(ratelimit)) { + __print_extlog_rcd(pfx, estatus, cpu); + return 0; + } + + return 1; +} + +static int extlog_print(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct mce *mce = (struct mce *)data; + int bank = mce->bank; + int cpu = mce->extcpu; + struct acpi_generic_status *estatus; + int rc; + + estatus = extlog_elog_entry_check(cpu, bank); + if (estatus == NULL) + return NOTIFY_DONE; + + memcpy(elog_buf, (void *)estatus, ELOG_ENTRY_LEN); + /* clear record status to enable BIOS to update it again */ + estatus->block_status = 0; + + rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); + + return NOTIFY_DONE; +} + +static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) +{ + struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_object_list input; + union acpi_object params[4], *obj; + u8 uuid[16]; + int i; + + acpi_str_to_uuid(extlog_dsm_uuid, uuid); + input.count = 4; + input.pointer = params; + params[0].type = ACPI_TYPE_BUFFER; + params[0].buffer.length = 16; + params[0].buffer.pointer = uuid; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = rev; + params[2].type = ACPI_TYPE_INTEGER; + params[2].integer.value = func; + params[3].type = ACPI_TYPE_PACKAGE; + params[3].package.count = 0; + params[3].package.elements = NULL; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) + return -1; + + *ret = 0; + obj = (union acpi_object *)buf.pointer; + if (obj->type == ACPI_TYPE_INTEGER) { + *ret = obj->integer.value; + } else if (obj->type == ACPI_TYPE_BUFFER) { + if (obj->buffer.length <= 8) { + for (i = 0; i < obj->buffer.length; i++) + *ret |= (obj->buffer.pointer[i] << (i * 8)); + } + } + kfree(buf.pointer); + + return 0; +} + +static bool extlog_get_l1addr(void) +{ + acpi_handle handle; + u64 ret; + + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) + return false; + + if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_QUERY, &ret) || + !(ret & EXTLOG_QUERY_L1_EXIST)) + return false; + + if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_ADDR, &ret)) + return false; + + l1_dirbase = ret; + /* Spec says L1 directory must be 4K aligned, bail out if it isn't */ + if (l1_dirbase & ((1 << 12) - 1)) { + pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n", + l1_dirbase); + return false; + } + + return true; +} +static struct notifier_block extlog_mce_dec = { + .notifier_call = extlog_print, +}; + +static int __init extlog_init(void) +{ + struct extlog_l1_head *l1_head; + void __iomem *extlog_l1_hdr; + size_t l1_hdr_size; + struct resource *r; + u64 cap; + int rc; + + rc = -ENODEV; + + rdmsrl(MSR_IA32_MCG_CAP, cap); + if (!(cap & MCG_ELOG_P)) + return rc; + + if (!extlog_get_l1addr()) + return rc; + + rc = -EINVAL; + /* get L1 header to fetch necessary information */ + l1_hdr_size = sizeof(struct extlog_l1_head); + r = request_mem_region(l1_dirbase, l1_hdr_size, "L1 DIR HDR"); + if (!r) { + pr_warn(FW_BUG EMCA_BUG, + (unsigned long long)l1_dirbase, + (unsigned long long)l1_dirbase + l1_hdr_size); + goto err; + } + + extlog_l1_hdr = acpi_os_map_memory(l1_dirbase, l1_hdr_size); + l1_head = (struct extlog_l1_head *)extlog_l1_hdr; + l1_size = l1_head->total_len; + l1_percpu_entry = l1_head->entries; + elog_base = l1_head->elog_base; + elog_size = l1_head->elog_len; + acpi_os_unmap_memory(extlog_l1_hdr, l1_hdr_size); + release_mem_region(l1_dirbase, l1_hdr_size); + + /* remap L1 header again based on completed information */ + r = request_mem_region(l1_dirbase, l1_size, "L1 Table"); + if (!r) { + pr_warn(FW_BUG EMCA_BUG, + (unsigned long long)l1_dirbase, + (unsigned long long)l1_dirbase + l1_size); + goto err; + } + extlog_l1_addr = acpi_os_map_memory(l1_dirbase, l1_size); + l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size); + + /* remap elog table */ + r = request_mem_region(elog_base, elog_size, "Elog Table"); + if (!r) { + pr_warn(FW_BUG EMCA_BUG, + (unsigned long long)elog_base, + (unsigned long long)elog_base + elog_size); + goto err_release_l1_dir; + } + elog_addr = acpi_os_map_memory(elog_base, elog_size); + + rc = -ENOMEM; + /* allocate buffer to save elog record */ + elog_buf = kmalloc(ELOG_ENTRY_LEN, GFP_KERNEL); + if (elog_buf == NULL) + goto err_release_elog; + + mce_register_decode_chain(&extlog_mce_dec); + /* enable OS to be involved to take over management from BIOS */ + ((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN; + + return 0; + +err_release_elog: + if (elog_addr) + acpi_os_unmap_memory(elog_addr, elog_size); + release_mem_region(elog_base, elog_size); +err_release_l1_dir: + if (extlog_l1_addr) + acpi_os_unmap_memory(extlog_l1_addr, l1_size); + release_mem_region(l1_dirbase, l1_size); +err: + pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n"); + return rc; +} + +static void __exit extlog_exit(void) +{ + mce_unregister_decode_chain(&extlog_mce_dec); + ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; + if (extlog_l1_addr) + acpi_os_unmap_memory(extlog_l1_addr, l1_size); + if (elog_addr) + acpi_os_unmap_memory(elog_addr, elog_size); + release_mem_region(elog_base, elog_size); + release_mem_region(l1_dirbase, l1_size); + kfree(elog_buf); +} + +module_init(extlog_init); +module_exit(extlog_exit); + +MODULE_AUTHOR("Chen, Gong "); +MODULE_DESCRIPTION("Extended MCA Error Log Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b587ec8257b2..e1bd9a181117 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -174,7 +174,7 @@ static void acpi_print_osc_error(acpi_handle handle, printk("\n"); } -static acpi_status acpi_str_to_uuid(char *str, u8 *uuid) +acpi_status acpi_str_to_uuid(char *str, u8 *uuid) { int i; static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, @@ -195,6 +195,7 @@ static acpi_status acpi_str_to_uuid(char *str, u8 *uuid) } return AE_OK; } +EXPORT_SYMBOL_GPL(acpi_str_to_uuid); acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) { -- cgit v1.2.3 From 147de14772ed897727dba7353916b02d1e0f17f4 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 18 Oct 2013 14:30:13 -0700 Subject: ACPI, APEI, CPER: Add UEFI 2.4 support for memory error In latest UEFI spec(by now it is 2.4) memory error definition for CPER (UEFI 2.4 Appendix N Common Platform Error Record) adds some new fields. These fields help people to locate memory error to an actual DIMM location. Original-author: Tony Luck Signed-off-by: Chen, Gong Reviewed-by: Borislav Petkov Reviewed-by: Mauro Carvalho Chehab Acked-by: Naveen N. Rao Signed-off-by: Tony Luck --- drivers/acpi/apei/cper.c | 7 ++++--- drivers/acpi/apei/ghes.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index eb5f6d6d7dbc..946ef520186f 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -8,7 +8,7 @@ * various tables, such as ERST, BERT and HEST etc. * * For more information about CPER, please refer to Appendix N of UEFI - * Specification version 2.3. + * Specification version 2.4. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -191,16 +191,17 @@ static const char *cper_mem_err_type_strs[] = { "memory sparing", "scrub corrected error", "scrub uncorrected error", + "physical memory map-out event", }; static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) { if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); - if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) + if (mem->validation_bits & CPER_MEM_VALID_PA) printk("%s""physical_address: 0x%016llx\n", pfx, mem->physical_addr); - if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK) + if (mem->validation_bits & CPER_MEM_VALID_PA_MASK) printk("%s""physical_address_mask: 0x%016llx\n", pfx, mem->physical_addr_mask); if (mem->validation_bits & CPER_MEM_VALID_NODE) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 0db6e4ff6501..a30bc313787b 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -419,7 +419,7 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) if (sec_sev == GHES_SEV_CORRECTED && (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) && - (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS)) { + (mem_err->validation_bits & CPER_MEM_VALID_PA)) { pfn = mem_err->physical_addr >> PAGE_SHIFT; if (pfn_valid(pfn)) memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE); @@ -430,7 +430,7 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) } if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE && - mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) { + mem_err->validation_bits & CPER_MEM_VALID_PA) { pfn = mem_err->physical_addr >> PAGE_SHIFT; memory_failure_queue(pfn, 0, 0); } -- cgit v1.2.3 From fbeef85fd2ccdd61568c86fe33d6ad6b79851a53 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 18 Oct 2013 14:30:21 -0700 Subject: ACPI, APEI, CPER: Enhance memory reporting capability After H/W error happens under FFM enabled mode, lots of information are shown but new fields added by UEFI 2.4 (e.g. DIMM location) need to be added. Original-author: Tony Luck Signed-off-by: Chen, Gong Acked-by: Naveen N. Rao Acked-by: Borislav Petkov Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Tony Luck --- drivers/acpi/apei/cper.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index 946ef520186f..b1a8a55915d9 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -210,6 +211,8 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) printk("%s""card: %d\n", pfx, mem->card); if (mem->validation_bits & CPER_MEM_VALID_MODULE) printk("%s""module: %d\n", pfx, mem->module); + if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) + printk("%s""rank: %d\n", pfx, mem->rank); if (mem->validation_bits & CPER_MEM_VALID_BANK) printk("%s""bank: %d\n", pfx, mem->bank); if (mem->validation_bits & CPER_MEM_VALID_DEVICE) @@ -232,6 +235,15 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) etype < ARRAY_SIZE(cper_mem_err_type_strs) ? cper_mem_err_type_strs[etype] : "unknown"); } + if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) { + const char *bank = NULL, *device = NULL; + dmi_memdev_name(mem->mem_dev_handle, &bank, &device); + if (bank != NULL && device != NULL) + printk("%s""DIMM location: %s %s", pfx, bank, device); + else + printk("%s""DIMM DMI handle: 0x%.4x", + pfx, mem->mem_dev_handle); + } } static const char *cper_pcie_port_type_strs[] = { -- cgit v1.2.3 From f6edea77c8c83760d74356ce6bd45d530d32b27f Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 18 Oct 2013 14:30:29 -0700 Subject: ACPI, APEI, CPER: Cleanup CPER memory error output format Memory error reporting is much too verbose. Most users do not care about the DIMM internal bank/row/column information. Downgrade the fine details to "pr_debug" status so that those few who do care can get them if they really want to. The detail information will be later be provided by perf/trace interface. Since things are still a bit scary, and users are sometimes overly nervous, provide a reassuring message that corrected errors do not generally require any further action. Suggested-by: Tony Luck Signed-off-by: Chen, Gong Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Tony Luck --- drivers/acpi/apei/cper.c | 67 ++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index b1a8a55915d9..1491dd4f08f9 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -33,6 +33,7 @@ #include #include +#define INDENT_SP " " /* * CPER record ID need to be unique even after reboot, because record * ID is used as index for ERST storage, while CPER records from @@ -206,29 +207,29 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) printk("%s""physical_address_mask: 0x%016llx\n", pfx, mem->physical_addr_mask); if (mem->validation_bits & CPER_MEM_VALID_NODE) - printk("%s""node: %d\n", pfx, mem->node); + pr_debug("node: %d\n", mem->node); if (mem->validation_bits & CPER_MEM_VALID_CARD) - printk("%s""card: %d\n", pfx, mem->card); + pr_debug("card: %d\n", mem->card); if (mem->validation_bits & CPER_MEM_VALID_MODULE) - printk("%s""module: %d\n", pfx, mem->module); + pr_debug("module: %d\n", mem->module); if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) - printk("%s""rank: %d\n", pfx, mem->rank); + pr_debug("rank: %d\n", mem->rank); if (mem->validation_bits & CPER_MEM_VALID_BANK) - printk("%s""bank: %d\n", pfx, mem->bank); + pr_debug("bank: %d\n", mem->bank); if (mem->validation_bits & CPER_MEM_VALID_DEVICE) - printk("%s""device: %d\n", pfx, mem->device); + pr_debug("device: %d\n", mem->device); if (mem->validation_bits & CPER_MEM_VALID_ROW) - printk("%s""row: %d\n", pfx, mem->row); + pr_debug("row: %d\n", mem->row); if (mem->validation_bits & CPER_MEM_VALID_COLUMN) - printk("%s""column: %d\n", pfx, mem->column); + pr_debug("column: %d\n", mem->column); if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) - printk("%s""bit_position: %d\n", pfx, mem->bit_pos); + pr_debug("bit_position: %d\n", mem->bit_pos); if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) - printk("%s""requestor_id: 0x%016llx\n", pfx, mem->requestor_id); + pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id); if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) - printk("%s""responder_id: 0x%016llx\n", pfx, mem->responder_id); + pr_debug("responder_id: 0x%016llx\n", mem->responder_id); if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) - printk("%s""target_id: 0x%016llx\n", pfx, mem->target_id); + pr_debug("target_id: 0x%016llx\n", mem->target_id); if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { u8 etype = mem->error_type; printk("%s""error_type: %d, %s\n", pfx, etype, @@ -296,55 +297,45 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, pfx, pcie->bridge.secondary_status, pcie->bridge.control); } -static const char * const cper_estatus_section_flag_strs[] = { - "primary", - "containment warning", - "reset", - "error threshold exceeded", - "resource not accessible", - "latent error", -}; - static void cper_estatus_print_section( const char *pfx, const struct acpi_generic_data *gdata, int sec_no) { uuid_le *sec_type = (uuid_le *)gdata->section_type; __u16 severity; + char newpfx[64]; severity = gdata->error_severity; - printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity, + printk("%s""Error %d, type: %s\n", pfx, sec_no, cper_severity_str(severity)); - printk("%s""flags: 0x%02x\n", pfx, gdata->flags); - cper_print_bits(pfx, gdata->flags, cper_estatus_section_flag_strs, - ARRAY_SIZE(cper_estatus_section_flag_strs)); if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); + snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); - printk("%s""section_type: general processor error\n", pfx); + printk("%s""section_type: general processor error\n", newpfx); if (gdata->error_data_length >= sizeof(*proc_err)) - cper_print_proc_generic(pfx, proc_err); + cper_print_proc_generic(newpfx, proc_err); else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); - printk("%s""section_type: memory error\n", pfx); + printk("%s""section_type: memory error\n", newpfx); if (gdata->error_data_length >= sizeof(*mem_err)) - cper_print_mem(pfx, mem_err); + cper_print_mem(newpfx, mem_err); else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { struct cper_sec_pcie *pcie = (void *)(gdata + 1); - printk("%s""section_type: PCIe error\n", pfx); + printk("%s""section_type: PCIe error\n", newpfx); if (gdata->error_data_length >= sizeof(*pcie)) - cper_print_pcie(pfx, pcie, gdata); + cper_print_pcie(newpfx, pcie, gdata); else goto err_section_too_small; } else - printk("%s""section type: unknown, %pUl\n", pfx, sec_type); + printk("%s""section type: unknown, %pUl\n", newpfx, sec_type); return; @@ -358,17 +349,21 @@ void cper_estatus_print(const char *pfx, struct acpi_generic_data *gdata; unsigned int data_len, gedata_len; int sec_no = 0; + char newpfx[64]; __u16 severity; - printk("%s""Generic Hardware Error Status\n", pfx); severity = estatus->error_severity; - printk("%s""severity: %d, %s\n", pfx, severity, - cper_severity_str(severity)); + if (severity == CPER_SEV_CORRECTED) + printk("%s%s\n", pfx, + "It has been corrected by h/w " + "and requires no further action"); + printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); data_len = estatus->data_length; gdata = (struct acpi_generic_data *)(estatus + 1); + snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; - cper_estatus_print_section(pfx, gdata, sec_no); + cper_estatus_print_section(newpfx, gdata, sec_no); data_len -= gedata_len + sizeof(*gdata); gdata = (void *)(gdata + 1) + gedata_len; sec_no++; -- cgit v1.2.3 From e37f14a5fb85522f3bbf88ece6134c4e610ed598 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 18 Oct 2013 15:56:44 +0400 Subject: ACPI / video: Ignore BIOS initial backlight value for HP 250 G1 On HP 250 G1 laptops, BIOS reports minimum backlight on boot and causes backlight to dim completely. This ignores the initial backlight values and set to max brightness. References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Signed-off-by: Kirill Tkhai Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d020df5a732a..38c3a28d6392 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -504,6 +504,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP 250 G1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"), + }, + }, {} }; -- cgit v1.2.3 From 1bdb71af7f1388fd4b305134035008a81f2032b8 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 22 Oct 2013 16:53:35 +0200 Subject: ACPI: Add Toshiba NB100 to Vista _OSI blacklist This patch adds Toshiba NB100 to the Vista _OSI blacklist. The _OSI(Windows 2006) method is bugged on the netbook resulting in messed up PCI IRQ Routing information. This was observed on a netbook whose SATA controller mode was set to Compatibility mode. The controller would then issue IRQs to IRQ#16 instead of IRQ#20, where it should have been. No side-effects were found during testing, everything is working as it did before. References: http://marc.info/?t=137862230200001&r=1&w=2 References: http://www.spinics.net/lists/linux-ide/msg46173.html Signed-off-by: Levente Kurusa Reviewed-by: Robert Hancock Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index aa4d874a96fd..b7fd1aeb6c42 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba NB100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), + }, + }, /* * The following machines have broken backlight support when reporting -- cgit v1.2.3 From b042453f3892465e8372b95a0f42c0890df03445 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 22 Oct 2013 16:53:35 +0200 Subject: ACPI: Add Toshiba NB100 to Vista _OSI blacklist This patch adds Toshiba NB100 to the Vista _OSI blacklist. The _OSI(Windows 2006) method is bugged on the netbook resulting in messed up PCI IRQ Routing information. This was observed on a netbook whose SATA controller mode was set to Compatibility mode. The controller would then issue IRQs to IRQ#16 instead of IRQ#20, where it should have been. No side-effects were found during testing, everything is working as it did before. References: http://marc.info/?t=137862230200001&r=1&w=2 References: http://www.spinics.net/lists/linux-ide/msg46173.html Signed-off-by: Levente Kurusa Reviewed-by: Robert Hancock Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index aa4d874a96fd..b7fd1aeb6c42 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba NB100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), + }, + }, /* * The following machines have broken backlight support when reporting -- cgit v1.2.3 From 34411a69a4925dd6de8e1069956f59d758da3ce9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Oct 2013 00:00:30 +0100 Subject: ACPI / processor: Do not request ACPI cpufreq module directly Function acpi_processor_load_module() used by the ACPI processor driver can only really work if the acpi-cpufreq module is available when acpi_processor_start() is executed which usually is not the case for systems loading the processor driver module from an initramfs. Moreover, that used to be a hackish workaround for module autoloading issues, but udev loads acpi-cpufreq just fine nowadays, so that function isn't really necessary any more. For this reason, drop acpi_processor_load_module() entirely. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_driver.c | 1 - drivers/acpi/processor_perflib.c | 22 ---------------------- 2 files changed, 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 40fc773ab6e0..146ab7e2b81d 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -171,7 +171,6 @@ static int __acpi_processor_start(struct acpi_device *device) #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_load_module(pr); #endif acpi_processor_get_throttling_info(pr); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 51d7948611da..60a7c28fc167 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -235,28 +235,6 @@ void acpi_processor_ppc_exit(void) acpi_processor_ppc_status &= ~PPC_REGISTERED; } -/* - * Do a quick check if the systems looks like it should use ACPI - * cpufreq. We look at a _PCT method being available, but don't - * do a whole lot of sanity checks. - */ -void acpi_processor_load_module(struct acpi_processor *pr) -{ - static int requested; - acpi_status status = 0; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - if (!arch_has_acpi_pdc() || requested) - return; - status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); - if (!ACPI_FAILURE(status)) { - printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n"); - request_module_nowait("acpi_cpufreq"); - requested = 1; - } - kfree(buffer.pointer); -} - static int acpi_processor_get_performance_control(struct acpi_processor *pr) { int result = 0; -- cgit v1.2.3 From e7e92ec93f218085e37ded8338f717ffd49eed1d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 29 Oct 2013 10:34:19 +0000 Subject: ACPI: Fix spelling mistake in error messages Fix spelling mistake "expecing" --> "expecting" Signed-off-by: Colin Ian King Signed-off-by: Rafael J. Wysocki --- drivers/acpi/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index fc2cd3284080..6d408bfbbb1d 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -121,7 +121,7 @@ acpi_extract_package(union acpi_object *package, break; default: printk(KERN_WARNING PREFIX "Invalid package element" - " [%d]: got number, expecing" + " [%d]: got number, expecting" " [%c]\n", i, format_string[i]); return AE_BAD_DATA; @@ -148,7 +148,7 @@ acpi_extract_package(union acpi_object *package, default: printk(KERN_WARNING PREFIX "Invalid package element" " [%d] got string/buffer," - " expecing [%c]\n", + " expecting [%c]\n", i, format_string[i]); return AE_BAD_DATA; break; -- cgit v1.2.3 From 1b673f23d95f0bbc7e3c95321864b727ea75704b Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Tue, 29 Oct 2013 09:28:49 +0800 Subject: ACPICA: Ensure that debug output is immediately disabled on termination. Set the global debug flag to "no output" when the debugger is shutdown. ACPICA BZ 1011. Tomasz Nowicki. Since the debugger is not shipped in the Linux kernel upstream, this change doesn't affect Linux kernel's behavior. References: https://bugs.acpica.org/show_bug.cgi?id=1011 Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index be9e30ee6048..dafa0f6c5fe8 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1094,6 +1094,7 @@ struct acpi_integrity_info { u32 objects; }; +#define ACPI_DB_DISABLE_OUTPUT 0x00 #define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 #define ACPI_DB_CONSOLE_OUTPUT 0x02 #define ACPI_DB_DUPLICATE_OUTPUT 0x03 -- cgit v1.2.3 From d7da179423a506e8033a376547a375c0c9ec7671 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:28:56 +0800 Subject: ACPICA: Table print header function: Increase default width for table length. This change increases the default width for the length of tables from 5 to 6, to improve alignment/readability on systems with large tables. These are being seen more frequently, especially large DSDTs (greater than 1 MB). Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbprint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 9a47715af1f3..6866e767ba90 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -135,7 +135,7 @@ acpi_tb_print_table_header(acpi_physical_address address, /* FACS only has signature and length fields */ - ACPI_INFO((AE_INFO, "%4.4s %p %05X", + ACPI_INFO((AE_INFO, "%4.4s %p %06X", header->signature, ACPI_CAST_PTR(void, address), header->length)); } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { @@ -147,7 +147,7 @@ acpi_tb_print_table_header(acpi_physical_address address, header)->oem_id, ACPI_OEM_ID_SIZE); acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)", ACPI_CAST_PTR(void, address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> revision > @@ -162,7 +162,7 @@ acpi_tb_print_table_header(acpi_physical_address address, acpi_tb_cleanup_table_header(&local_header, header); ACPI_INFO((AE_INFO, - "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", local_header.signature, ACPI_CAST_PTR(void, address), local_header.length, local_header.revision, local_header.oem_id, local_header.oem_table_id, -- cgit v1.2.3 From 48961ce62787502fe2afce2aeeb0ec306757a2bb Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:04 +0800 Subject: ACPICA: Add a check for a null node during namespace walk. Mostly for consistency. ACPICA BZ 1042. Actually, currently no one is experiencing problem without this check as the obj_handle is guaranteed to be valid. References: https://bugs.acpica.org/show_bug.cgi?id=1042 Reported-by: Colin Ian King Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsdump.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 80633851cb2f..c6348545277e 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -715,6 +715,13 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle, } node = acpi_ns_validate_handle(obj_handle); + if (!node) { + + /* Ignore bad node during namespace walk */ + + return (AE_OK); + } + pathname = acpi_ns_get_external_pathname(node); path_indent = 1; -- cgit v1.2.3 From 1d98e9e0bb8815072a0d2d04dc3f0e2c51029e61 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:09 +0800 Subject: ACPICA: Add history/line-editing for Unix/Linux systems. The original upstream ACPICA change added full history and limited line editing to the debugger: This change adds full history and limited line editing for Unix and Linux systems. It does not use readline() because of portability issues. Instead it uses the POSIX termio interface to put the terminal in raw input mode so that the various special keys can be trapped (such as up-arrow and down-arrow for history support). Since the debugger is not shipped in the kernel, it only is necessary to update one header file to keep the kernel source in sync with the upstream. [rjw: Changelog] Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 27c36a5251b5..57cdc770fba8 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -243,6 +243,8 @@ void acpi_db_display_history(void); char *acpi_db_get_from_history(char *command_num_arg); +char *acpi_db_get_history_by_index(u32 commandd_num); + /* * dbinput - user front-end to the AML debugger */ -- cgit v1.2.3 From 73424473d0801f7079258897901ba1edc660dbd3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:21 +0800 Subject: ACPICA: Add safe versions of common string functions. This change adds and deploys "safe" versions of strcpy and strcat that ensure that the target buffer does not overflow. These safe functions are only helpful for processing user input and command lines. For most ACPICA code however, the required buffer length is precisely calculated before buffer allocation, so the use of these functions is unnecessary. ACPICA BZ 1043. This change only applies to the ACPICA utilities and the debugger, none of which are not shipped with the kernel yet, so the kernel's behavior remains unchanged after it. References: https://bugs.acpica.org/show_bug.cgi?id=1043 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 2 +- drivers/acpi/acpica/acutils.h | 11 ++++++++ drivers/acpi/acpica/utstring.c | 62 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index dafa0f6c5fe8..53ed1a8ba4f0 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1072,7 +1072,7 @@ struct acpi_db_method_info { char *name; u32 flags; u32 num_loops; - char pathname[128]; + char pathname[ACPI_DB_LINE_BUFFER_SIZE]; char **args; acpi_object_type *types; diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index d5a62a6182bb..4f25e8f0cd5f 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -628,6 +628,17 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position); void acpi_ut_repair_name(char *name); +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source); + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source); + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length); +#endif + /* * utmutex - mutex support */ diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index cb1e9cc32d5f..5ef41ffcf575 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -584,3 +584,65 @@ void ut_convert_backslashes(char *pathname) } } #endif + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +/******************************************************************************* + * + * FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source) +{ + + if (ACPI_STRLEN(source) >= dest_size) { + return (TRUE); + } + + ACPI_STRCPY(dest, source); + return (FALSE); +} + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source) +{ + + if ((ACPI_STRLEN(dest) + ACPI_STRLEN(source)) >= dest_size) { + return (TRUE); + } + + ACPI_STRCAT(dest, source); + return (FALSE); +} + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length) +{ + acpi_size actual_transfer_length; + + actual_transfer_length = + ACPI_MIN(max_transfer_length, ACPI_STRLEN(source)); + + if ((ACPI_STRLEN(dest) + actual_transfer_length) >= dest_size) { + return (TRUE); + } + + ACPI_STRNCAT(dest, source, max_transfer_length); + return (FALSE); +} +#endif -- cgit v1.2.3 From b3c86c30efd83ebfa7010c5890e2ebf2678e49f8 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:27 +0800 Subject: ACPICA: Cleanup memory allocation macros and configurability. In the common case, the ACPI_ALLOCATE and related macros now resolve directly to their respective acpi_os* OSL interfaces. Two options: 1) The ACPI_ALLOCATE_ZEROED macro defaults to a simple local implementation by default, unless overridden by the USE_NATIVE_ALLOCATE_ZEROED define. 2) For ACPI execution simulation environment (AcpiExec) which is not shipped with the Linux kernel, the macros can optionally be resolved to the local interfaces that track each allocation (used to immediately detect memory leaks). Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acmacros.h | 31 ----------- drivers/acpi/acpica/acutils.h | 6 --- drivers/acpi/acpica/utalloc.c | 113 +++++++++++++---------------------------- drivers/acpi/acpica/uttrack.c | 29 +++++++++-- 4 files changed, 59 insertions(+), 120 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 530a2f8c1252..2a86c65d873b 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -409,37 +409,6 @@ #define ACPI_DEBUGGER_EXEC(a) #endif -/* - * Memory allocation tracking (DEBUG ONLY) - */ -#define ACPI_MEM_PARAMETERS _COMPONENT, _acpi_module_name, __LINE__ - -#ifndef ACPI_DBG_TRACK_ALLOCATIONS - -/* Memory allocation */ - -#ifndef ACPI_ALLOCATE -#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_ALLOCATE_ZEROED -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_FREE -#define ACPI_FREE(a) acpi_os_free(a) -#endif -#define ACPI_MEM_TRACKING(a) - -#else - -/* Memory allocation */ - -#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) -#define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS) -#define ACPI_MEM_TRACKING(a) a - -#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - /* * Macros used for ACPICA utilities only */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 4f25e8f0cd5f..be8180c17d7e 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -663,12 +663,6 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length); -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line); - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line); - #ifdef ACPI_DBG_TRACK_ALLOCATIONS void *acpi_ut_allocate_and_track(acpi_size size, u32 component, const char *module, u32 line); diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index e0ffb580f4b0..d84479610971 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -48,6 +48,39 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") +#if !defined (USE_NATIVE_ALLOCATE_ZEROED) +/******************************************************************************* + * + * FUNCTION: acpi_os_allocate_zeroed + * + * PARAMETERS: size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * This is the default implementation. Can be overridden via the + * USE_NATIVE_ALLOCATE_ZEROED flag. + * + ******************************************************************************/ +void *acpi_os_allocate_zeroed(acpi_size size) +{ + void *allocation; + + ACPI_FUNCTION_ENTRY(); + + allocation = acpi_os_allocate(size); + if (allocation) { + + /* Clear the memory block */ + + ACPI_MEMSET(allocation, 0, size); + } + + return (allocation); +} + +#endif /* !USE_NATIVE_ALLOCATE_ZEROED */ + /******************************************************************************* * * FUNCTION: acpi_ut_create_caches @@ -59,6 +92,7 @@ ACPI_MODULE_NAME("utalloc") * DESCRIPTION: Create all local caches * ******************************************************************************/ + acpi_status acpi_ut_create_caches(void) { acpi_status status; @@ -302,82 +336,3 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, ACPI_MEMSET(buffer->pointer, 0, required_length); return (AE_OK); } - -#ifdef NOT_USED_BY_LINUX -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate - * - * PARAMETERS: size - Size of the allocation - * component - Component type of caller - * module - Source file name of caller - * line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_TRACE_U32(ut_allocate, size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_WARNING((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - - /* Report allocation error */ - - ACPI_WARNING((module, line, - "Could not allocate size %u", (u32) size)); - - return_PTR(NULL); - } - - return_PTR(allocation); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_zeroed - * - * PARAMETERS: size - Size of the allocation - * component - Component type of caller - * module - Source file name of caller - * line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. - * - ******************************************************************************/ - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_ENTRY(); - - allocation = acpi_ut_allocate(size, component, module, line); - if (allocation) { - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - } - - return (allocation); -} -#endif diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 160f13f4aab5..77e3eb7d7c04 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -130,10 +130,23 @@ void *acpi_ut_allocate_and_track(acpi_size size, struct acpi_debug_mem_block *allocation; acpi_status status; + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + allocation = - acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); + acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header)); if (!allocation) { + + /* Report allocation error */ + + ACPI_WARNING((module, line, + "Could not allocate size %u", (u32)size)); + return (NULL); } @@ -179,9 +192,17 @@ void *acpi_ut_allocate_zeroed_and_track(acpi_size size, struct acpi_debug_mem_block *allocation; acpi_status status; + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + allocation = - acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header), - component, module, line); + acpi_os_allocate_zeroed(size + + sizeof(struct acpi_debug_mem_header)); if (!allocation) { /* Report allocation error */ -- cgit v1.2.3 From ab3b24807adabdc32f8a9d5d7d3902e1e744d139 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:40 +0800 Subject: ACPICA: Fix possible memory leaks in the GPE handling. This change fixes potential memory leaks in the error paths of the GPE handling code. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evgpe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index c8a1f7d5931f..1979a256be3b 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -522,6 +522,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { + ACPI_FREE(local_gpe_event_info); return_VOID; } -- cgit v1.2.3 From e07fcfd89f9bbbc5f655b85b70e6f9b0bb626bac Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:45 +0800 Subject: ACPICA: Hardcode access width for the reset register. The ACPI spec requires the reset register width to be 8, so we now hardcode it and ignore the FADT value. This provides/maintains compatibility with other ACPI implementations that have allowed BIOS code with bad register width values to go unnoticed. Matthew Garett, Bob Moore, Lv Zheng. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwxface.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index f81fb068d20e..d3682c2ae0d1 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -83,11 +83,17 @@ acpi_status acpi_reset(void) * For I/O space, write directly to the OSL. This bypasses the port * validation mechanism, which may block a valid write to the reset * register. - * Spec section 4.7.3.6 requires register width to be 8. + * + * NOTE: + * The ACPI spec requires the reset register width to be 8, so we + * hardcode it here and ignore the FADT value. This maintains + * compatibility with other ACPI implementations that have allowed + * BIOS code with bad register width values to go unnoticed. */ status = acpi_os_write_port((acpi_io_address) reset_reg->address, - acpi_gbl_FADT.reset_value, 8); + acpi_gbl_FADT.reset_value, + ACPI_RESET_REGISTER_WIDTH); } else { /* Write the reset value to the reset register */ -- cgit v1.2.3 From 839e928f5bbb695c31ddc23cf3fae3cf1c9e9f20 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:51 +0800 Subject: ACPICA: Add EXPORT_ACPI_INTERFACES macro to external interface modules. For Linux, there are no functional changes/binary generation differences introduced by this patch. This change adds a new macro to all files that contain external ACPICA interfaces. It can be detected and used by the host (via the host-specific header) for any special processing required for such modules. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evxface.c | 3 ++- drivers/acpi/acpica/evxfevnt.c | 3 ++- drivers/acpi/acpica/evxfgpe.c | 3 ++- drivers/acpi/acpica/evxfregn.c | 3 ++- drivers/acpi/acpica/hwtimer.c | 3 ++- drivers/acpi/acpica/hwxface.c | 3 ++- drivers/acpi/acpica/hwxfsleep.c | 3 ++- drivers/acpi/acpica/nsxfeval.c | 3 ++- drivers/acpi/acpica/nsxfname.c | 3 ++- drivers/acpi/acpica/nsxfobj.c | 3 ++- drivers/acpi/acpica/rsxface.c | 3 ++- drivers/acpi/acpica/tbxface.c | 3 ++- drivers/acpi/acpica/tbxfload.c | 3 ++- drivers/acpi/acpica/utdebug.c | 3 ++- drivers/acpi/acpica/utdecode.c | 1 - drivers/acpi/acpica/utexcep.c | 3 ++- drivers/acpi/acpica/utglobal.c | 2 +- drivers/acpi/acpica/utxface.c | 3 ++- drivers/acpi/acpica/utxferror.c | 3 ++- drivers/acpi/acpica/utxfinit.c | 3 ++- 20 files changed, 37 insertions(+), 20 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 6f56146a6f88..6d88b1368088 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 7039606a0ba8..39d06af5e347 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "actables.h" diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 7662f1a42ff6..fab40d9b3bd6 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acevents.h" diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 80cecf838591..1bd3225be468 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index 2d7d22ebc782..3c498dc1636e 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index d3682c2ae0d1..b1568481463a 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index f2e669db8b65..4895fca102dd 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 481a6b4a9b2f..a6e3bca48567 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 83c164434580..3a6d78a3f64e 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index c0853ef294e4..94e961cf6294 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 94e3517554f9..01e476988aae 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acresrc.h" diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ad11162482ff..2ad853275e39 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "actables.h" diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 0ba9e328d5d7..2620dbe96cfa 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index ffd0db509d34..1a67b3944b3b 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 11e2e02e1618..b3f31dd89a45 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -41,7 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index ff6d9e8aa842..3cf7b597edb9 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -41,8 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#define EXPORT_ACPI_INTERFACES + #define ACPI_DEFINE_EXCEPTION_TABLE -#include #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 046d5b059c07..4f59784b397d 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -41,9 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#define EXPORT_ACPI_INTERFACES #define DEFINE_ACPI_GLOBALS -#include #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 03a211e6e26a..2178da8af1a7 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acdebug.h" diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index e966a2e47b76..f7edb88f6054 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 41ebaaf8bb1a..dda18e622a93 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acevents.h" -- cgit v1.2.3 From bb1cab3d52375b5007645ca55d2b55167e5f757b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:57 +0800 Subject: ACPICA: Clarify ACPI_FREE_BUFFER usage. Add a comment to clarify reason for using ACPI_FREE_BUFFER directly instead of ACPI_FREE. In addition to that, change one instance in which ACPI_FREE_BUFFER() should be used instead of ACPI_FREE(). [rjw: Subject and changelog] Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsxfeval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index a6e3bca48567..ce2a84575a36 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -139,7 +139,7 @@ acpi_evaluate_object_typed(acpi_handle handle, /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - ACPI_FREE(return_buffer->pointer); + ACPI_FREE_BUFFER(*return_buffer); return_buffer->pointer = NULL; } -- cgit v1.2.3 From 10622bf8ce432e6a53fd3c37163e99e99c9e43ee Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:02 +0800 Subject: ACPICA: Linuxize: Change indentation of C labels. It is reported by kernel build test systems that all ACPICA source files in the kernel tree have incorrect label indentation. This patch changes default indent option used in the release process to fix this bug. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/dsargs.c | 2 +- drivers/acpi/acpica/dsfield.c | 2 +- drivers/acpi/acpica/dsmethod.c | 4 ++-- drivers/acpi/acpica/dsobject.c | 2 +- drivers/acpi/acpica/dsopcode.c | 2 +- drivers/acpi/acpica/dsutils.c | 10 +++++----- drivers/acpi/acpica/dswexec.c | 6 +++--- drivers/acpi/acpica/dswload2.c | 2 +- drivers/acpi/acpica/evglock.c | 2 +- drivers/acpi/acpica/evgpe.c | 2 +- drivers/acpi/acpica/evgpeblk.c | 6 +++--- drivers/acpi/acpica/evgpeinit.c | 2 +- drivers/acpi/acpica/evgpeutil.c | 2 +- drivers/acpi/acpica/evhandler.c | 4 ++-- drivers/acpi/acpica/evregion.c | 6 +++--- drivers/acpi/acpica/evxface.c | 12 ++++++------ drivers/acpi/acpica/evxfgpe.c | 6 +++--- drivers/acpi/acpica/evxfregn.c | 4 ++-- drivers/acpi/acpica/excreate.c | 8 ++++---- drivers/acpi/acpica/exfield.c | 2 +- drivers/acpi/acpica/exfldio.c | 2 +- drivers/acpi/acpica/exmisc.c | 4 ++-- drivers/acpi/acpica/exoparg1.c | 8 ++++---- drivers/acpi/acpica/exoparg2.c | 10 +++++----- drivers/acpi/acpica/exoparg3.c | 4 ++-- drivers/acpi/acpica/exoparg6.c | 2 +- drivers/acpi/acpica/exresolv.c | 2 +- drivers/acpi/acpica/exresop.c | 2 +- drivers/acpi/acpica/hwregs.c | 2 +- drivers/acpi/acpica/hwxface.c | 4 ++-- drivers/acpi/acpica/nsaccess.c | 2 +- drivers/acpi/acpica/nsdump.c | 2 +- drivers/acpi/acpica/nseval.c | 4 ++-- drivers/acpi/acpica/nsinit.c | 2 +- drivers/acpi/acpica/nsload.c | 2 +- drivers/acpi/acpica/nsparse.c | 2 +- drivers/acpi/acpica/nspredef.c | 2 +- drivers/acpi/acpica/nsprepkg.c | 4 ++-- drivers/acpi/acpica/nsrepair.c | 2 +- drivers/acpi/acpica/nsrepair2.c | 2 +- drivers/acpi/acpica/nsutils.c | 2 +- drivers/acpi/acpica/nsxfeval.c | 12 ++++++------ drivers/acpi/acpica/nsxfname.c | 4 ++-- drivers/acpi/acpica/nsxfobj.c | 4 ++-- drivers/acpi/acpica/psparse.c | 2 +- drivers/acpi/acpica/psxface.c | 6 +++--- drivers/acpi/acpica/rsmisc.c | 4 ++-- drivers/acpi/acpica/rsutils.c | 2 +- drivers/acpi/acpica/tbinstal.c | 6 +++--- drivers/acpi/acpica/tbutils.c | 2 +- drivers/acpi/acpica/tbxface.c | 4 ++-- drivers/acpi/acpica/tbxfload.c | 4 ++-- drivers/acpi/acpica/utcopy.c | 4 ++-- drivers/acpi/acpica/utdelete.c | 2 +- drivers/acpi/acpica/uteval.c | 2 +- drivers/acpi/acpica/utids.c | 2 +- drivers/acpi/acpica/utownerid.c | 2 +- drivers/acpi/acpica/utresrc.c | 4 ++-- drivers/acpi/acpica/utstring.c | 4 ++-- drivers/acpi/acpica/uttrack.c | 2 +- 60 files changed, 112 insertions(+), 112 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index fb09b08d7080..afdc6df17abf 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -158,7 +158,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, walk_state->deferred_node = node; status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index d4bfe7b7f90a..2d4c07322576 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -259,7 +259,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, goto cleanup; } - cleanup: +cleanup: /* Remove local reference to the object */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index a9ffd44c18fe..df3ea125507f 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -294,7 +294,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, obj_desc->method.thread_count++; return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, must release the method mutex (if present) */ if (obj_desc->method.mutex) { @@ -424,7 +424,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, we must terminate the method properly */ diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 63f0d220ca3d..b1746a68dad1 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -240,7 +240,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } - exit: +exit: *obj_desc_ptr = obj_desc; return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 1fc1ff114f26..5205edcf2c01 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -257,7 +257,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, (buffer_desc->common.reference_count + obj_desc->common.reference_count); - cleanup: +cleanup: /* Always delete the operands */ diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index c666fc014987..ade44e49deb4 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -299,7 +299,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_used; } - result_used: +result_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -308,7 +308,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, return_UINT8(TRUE); - result_not_used: +result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -752,7 +752,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); - cleanup: +cleanup: /* * We must undo everything done above; meaning that we must * pop everything off of the operand stack and delete those @@ -851,7 +851,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) goto exit; } - push_result: +push_result: walk_state->result_obj = new_obj_desc; @@ -863,7 +863,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) op->common.flags |= ACPI_PARSEOP_IN_STACK; } - exit: +exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 151d924817e1..1bbb22fd6fa0 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -170,7 +170,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); - cleanup: +cleanup: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", walk_state->control_state->common.value, @@ -335,7 +335,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); - error_exit: +error_exit: status = acpi_ds_method_error(status, walk_state); return_ACPI_STATUS(status); } @@ -722,7 +722,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) walk_state->result_obj = NULL; } - cleanup: +cleanup: if (walk_state->result_obj) { diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index b1f8f4725c23..7f569d573027 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -728,7 +728,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; } - cleanup: +cleanup: /* Remove the Node pushed at the very beginning */ diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index fdb0a76e40a3..4c67193a9fa7 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -173,7 +173,7 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_gbl_global_lock_pending = FALSE; - cleanup_and_exit: +cleanup_and_exit: acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); return (ACPI_INTERRUPT_HANDLED); diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 1979a256be3b..a9cb4a1a4bb8 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -458,7 +458,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) gpe_block = gpe_block->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return (int_status); diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index c1aa1eda26c3..a9e76bc4ad97 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -111,7 +111,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, gpe_block->xrupt_block = gpe_xrupt_block; acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -178,7 +178,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) ACPI_FREE(gpe_block->event_info); ACPI_FREE(gpe_block); - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -302,7 +302,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: if (gpe_register_info) { ACPI_FREE(gpe_register_info); } diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 7842700346a4..a3e2f38aadf6 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -203,7 +203,7 @@ acpi_status acpi_ev_gpe_initialize(void) goto cleanup; } - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index d52339090b60..d3f5e1e2a2b1 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -101,7 +101,7 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context) gpe_xrupt_info = gpe_xrupt_info->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index 068af96134b8..e3157313eb27 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -129,7 +129,7 @@ acpi_status acpi_ev_install_region_handlers(void) } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -531,6 +531,6 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, acpi_ev_install_handler, NULL, handler_obj, NULL); - unlock_and_exit: +unlock_and_exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 6293d6bb6fe1..144cbb9b73bc 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -573,10 +573,10 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) status = acpi_ns_evaluate(info); acpi_ut_remove_reference(args[1]); - cleanup2: +cleanup2: acpi_ut_remove_reference(args[0]); - cleanup1: +cleanup1: ACPI_FREE(info); return_ACPI_STATUS(status); } @@ -761,7 +761,7 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node) status = acpi_evaluate_object(reg_method, NULL, &args, NULL); - exit: +exit: /* We ignore all errors from above, don't care */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 6d88b1368088..23a7fadca412 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -375,7 +375,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) acpi_gbl_exception_handler = handler; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -445,12 +445,12 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) new_sci_handler->next = acpi_gbl_sci_handler_list; acpi_gbl_sci_handler_list = new_sci_handler; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - exit: +exit: if (ACPI_FAILURE(status)) { ACPI_FREE(new_sci_handler); } @@ -517,7 +517,7 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); status = AE_NOT_EXIST; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -566,7 +566,7 @@ acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) acpi_gbl_global_event_handler = handler; acpi_gbl_global_event_handler_context = context; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -638,7 +638,7 @@ acpi_install_fixed_event_handler(u32 event, handler)); } - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index fab40d9b3bd6..5713da77c665 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -472,7 +472,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) *event_status |= ACPI_EVENT_FLAG_HANDLE; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -625,7 +625,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, obj_desc->device.gpe_block = gpe_block; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -680,7 +680,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) obj_desc->device.gpe_block = NULL; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 1bd3225be468..02ed75ac56cd 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -148,7 +148,7 @@ acpi_install_address_space_handler(acpi_handle device, status = acpi_ev_execute_reg_methods(node, space_id); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -287,7 +287,7 @@ acpi_remove_address_space_handler(acpi_handle device, status = AE_NOT_EXIST; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 269e81d86ef4..3c2e6dcdad3e 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -193,7 +193,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) acpi_ns_attach_object((struct acpi_namespace_node *)walk_state-> operands[0], obj_desc, ACPI_TYPE_EVENT); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -248,7 +248,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, ACPI_TYPE_MUTEX); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -347,7 +347,7 @@ acpi_ex_create_region(u8 * aml_start, status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - cleanup: +cleanup: /* Remove local reference to the object */ @@ -520,7 +520,7 @@ acpi_ex_create_method(u8 * aml_start, acpi_ut_remove_reference(obj_desc); - exit: +exit: /* Remove a reference to the operand */ acpi_ut_remove_reference(operand[1]); diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index c2a65aaf29af..cfd875243421 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -197,7 +197,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - exit: +exit: if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(buffer_desc); } else { diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 7e0afe72487e..8ab01b613a18 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -1002,7 +1002,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); - exit: +exit: /* Free temporary buffer if we used one */ if (new_buffer) { diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 00bf29877574..65d93607f368 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -388,7 +388,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, *actual_return_desc = return_desc; - cleanup: +cleanup: if (local_operand1 != operand1) { acpi_ut_remove_reference(local_operand1); } @@ -718,7 +718,7 @@ acpi_ex_do_logical_op(u16 opcode, } } - cleanup: +cleanup: /* New object was created if implicit conversion performed - delete */ diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 2cdd41d8ade6..d74cea416ca0 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -115,7 +115,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) break; } - cleanup: +cleanup: /* Delete return object on error */ @@ -234,7 +234,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -551,7 +551,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[1], walk_state); } - cleanup: +cleanup: /* Delete return object on error */ @@ -1054,7 +1054,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index d5088f7030c7..d6fa0fce1fc9 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -215,7 +215,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* * Since the remainder is not returned indirectly, remove a reference to * it. Only the quotient is returned indirectly. @@ -445,7 +445,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) break; } - store_result_to_target: +store_result_to_target: if (ACPI_SUCCESS(status)) { /* @@ -462,7 +462,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) } } - cleanup: +cleanup: /* Delete return object on error */ @@ -553,7 +553,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - store_logical_result: +store_logical_result: /* * Set return value to according to logical_result. logical TRUE (all ones) * Default is FALSE (zero) @@ -562,7 +562,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_UINT64_MAX; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 37656f12f204..bc042adf8804 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -124,7 +124,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -252,7 +252,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[3], walk_state); - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 879b6cd8319c..4459e32c683d 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -314,7 +314,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index ac04278ad28f..1606524312e3 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -521,7 +521,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, */ type = obj_desc->common.type; - exit: +exit: /* Convert internal types to external types */ switch (type) { diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 00e5af7129c1..be3f66973ee8 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -683,7 +683,7 @@ acpi_ex_resolve_operands(u16 opcode, return_ACPI_STATUS(status); } - next_operand: +next_operand: /* * If more operands needed, decrement stack_ptr to point * to next operand on stack diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 8d2e866be15f..12e6cff54f78 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -560,7 +560,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; } - exit: +exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index b1568481463a..b4b47db2dee2 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -570,10 +570,10 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) break; } - cleanup1: +cleanup1: acpi_ut_remove_reference(info->return_object); - cleanup: +cleanup: if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While evaluating Sleep State [%s]", diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index aff79c7392ff..14f65f6345b9 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -240,7 +240,7 @@ acpi_status acpi_ns_root_initialize(void) } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index c6348545277e..48b9c6f12643 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -620,7 +620,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ } - cleanup: +cleanup: acpi_os_printf("\n"); return (AE_OK); } diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 18108bc2e51c..963ceef063f8 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -314,7 +314,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) "*** Completed evaluation of object %s ***\n", info->relative_pathname)); - cleanup: +cleanup: /* * Namespace was unlocked by the handling acpi_ns* function, so we * just free the pathname and return @@ -486,7 +486,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, parent_node->type = (u8)type; } - exit: +exit: if (parent_obj) { acpi_ut_remove_reference(parent_obj); } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index dd2ceae3f717..3a0423af968c 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -213,7 +213,7 @@ acpi_status acpi_ns_initialize_devices(void) return_ACPI_STATUS(status); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 0a7badc3179f..89ec645e7730 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -114,7 +114,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) (void)acpi_tb_release_owner_id(table_index); } - unlock: +unlock: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 35dde8151c0d..177857340271 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -140,7 +140,7 @@ acpi_ns_one_complete_parse(u32 pass_number, pass_number)); status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 098e7666cbc9..d2855d9857c4 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -271,7 +271,7 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info, return (AE_OK); /* Successful repair */ } - type_error_exit: +type_error_exit: /* Create a string with all expected types for this predefined object */ diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 6d55cef7916c..3d5391f9bcb5 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -330,7 +330,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, return (status); - package_too_small: +package_too_small: /* Error exit for the case with an incorrect package count */ @@ -555,7 +555,7 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, return (AE_OK); - package_too_small: +package_too_small: /* The sub-package count was smaller than required */ diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index f8e71ea60319..a05afff50eb9 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -263,7 +263,7 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info, return (AE_AML_OPERAND_TYPE); - object_repaired: +object_repaired: /* Object was successfully repaired */ diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index c84603ee83ae..6a25d320b169 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -478,7 +478,7 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, removing = TRUE; } - remove_element: +remove_element: if (removing) { acpi_ns_remove_element(return_object, i + 1); outer_element_count--; diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 08c0b5beec88..cc2fea94c5f0 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -722,7 +722,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - cleanup: +cleanup: ACPI_FREE(internal_path); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index ce2a84575a36..e973e311f856 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -442,7 +442,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_ex_exit_interpreter(); } - cleanup: +cleanup: /* Free the input parameter list (if we created one) */ @@ -618,10 +618,10 @@ acpi_walk_namespace(acpi_object_type type, descending_callback, ascending_callback, context, return_value); - unlock_and_exit2: +unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -865,7 +865,7 @@ acpi_attach_data(acpi_handle obj_handle, status = acpi_ns_attach_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -911,7 +911,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) status = acpi_ns_detach_data(node, handler); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -958,7 +958,7 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) status = acpi_ns_get_attached_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 3a6d78a3f64e..3a4bd3ff49a3 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -209,7 +209,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; status = AE_OK; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -497,7 +497,7 @@ acpi_get_object_info(acpi_handle handle, *return_buffer = info; status = AE_OK; - cleanup: +cleanup: if (hid) { ACPI_FREE(hid); } diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 94e961cf6294..0e6d79e462d4 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -201,7 +201,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) status = AE_NULL_ENTRY; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -281,7 +281,7 @@ acpi_get_next_object(acpi_object_type type, *ret_handle = ACPI_CAST_PTR(acpi_handle, node); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 86198a9139b5..79d9a28dedef 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -297,7 +297,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, } } - cleanup: +cleanup: /* Now we can actually delete the subtree rooted at Op */ diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 11b99ab20bb3..fcb7a840e996 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -142,7 +142,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) acpi_dbg_layer = acpi_gbl_trace_dbg_layer; } - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -185,7 +185,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) acpi_dbg_level = acpi_gbl_original_dbg_level; acpi_dbg_layer = acpi_gbl_original_dbg_layer; - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -323,7 +323,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* walk_state was deleted by parse_aml */ - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); /* End optional tracing */ diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index 80d12994e0d0..c99cec9cefde 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -440,7 +440,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, info++; } - exit: +exit: if (!flags_mode) { /* Round the resource struct length up to the next boundary (32 or 64) */ @@ -783,7 +783,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, info++; } - exit: +exit: return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 480b6b40c5ea..aef303d56d86 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -784,7 +784,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, acpi_ut_remove_reference(args[0]); - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 9e6788f9ba0f..634357d51fe9 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -231,10 +231,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) goto release; } - print_header: +print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); - release: +release: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } @@ -306,7 +306,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header return (NULL); /* There was no override */ - finish_override: +finish_override: ACPI_INFO((AE_INFO, "%4.4s %p %s table override, new table: %p", diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index bffdfc7b8322..43ffe21c7b26 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -350,7 +350,7 @@ acpi_tb_install_table(acpi_physical_address address, acpi_tb_delete_table(table_desc); } - unmap_and_exit: +unmap_and_exit: /* Always unmap the table header that we mapped above */ diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 2ad853275e39..bbaad5c4e2cd 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -466,7 +466,7 @@ acpi_install_table_handler(acpi_table_handler handler, void *context) acpi_gbl_table_handler = handler; acpi_gbl_table_handler_context = context; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -507,7 +507,7 @@ acpi_status acpi_remove_table_handler(acpi_table_handler handler) acpi_gbl_table_handler = NULL; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 2620dbe96cfa..5a2202495b0f 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -201,7 +201,7 @@ static acpi_status acpi_tb_load_namespace(void) ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } @@ -269,7 +269,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table) acpi_gbl_table_handler_context); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 1731c27c36a6..edff4e653d9a 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -552,7 +552,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, *ret_internal_object = internal_object; return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: acpi_ut_remove_reference(internal_object); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -899,7 +899,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, return (status); - error_exit: +error_exit: acpi_ut_remove_reference(target_object); return (status); } diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index d6b33f29d327..c07d2227ea42 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -649,7 +649,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) return (AE_OK); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 4fd68971019b..16fb90506db7 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -181,7 +181,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, *return_desc = info->return_object; - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index fa69071db418..bfca7b4b6731 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -184,7 +184,7 @@ acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, sub->length = length; *return_id = sub; - cleanup: +cleanup: /* On exit, we must delete the return object */ diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c index 835340b26d37..eb3aca761369 100644 --- a/drivers/acpi/acpica/utownerid.c +++ b/drivers/acpi/acpica/utownerid.c @@ -148,7 +148,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) ACPI_ERROR((AE_INFO, "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index cb7fa491decf..2c2accb9e534 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -643,7 +643,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state, return (AE_OK); - invalid_resource: +invalid_resource: if (walk_state) { ACPI_ERROR((AE_INFO, @@ -652,7 +652,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state, } return (AE_AML_INVALID_RESOURCE_TYPE); - bad_resource_length: +bad_resource_length: if (walk_state) { ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 5ef41ffcf575..45c0eb26b33d 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -310,7 +310,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) /* All done, normal exit */ - all_done: +all_done: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", ACPI_FORMAT_UINT64(return_value))); @@ -318,7 +318,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) *ret_integer = return_value; return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: /* Base was set/validated above */ if (base == 10) { diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 77e3eb7d7c04..c0027773cccb 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -430,7 +430,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, element->next = allocation; } - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); return_ACPI_STATUS(status); } -- cgit v1.2.3 From d21f600b0e4d5a694a338688e61d95f08dbf0afb Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:10 +0800 Subject: ACPICA: Deploy ACPI_EXPORT_SYMBOL_INIT for main ACPICA initialization interfaces. This changes can reduce source code differences between Linux and ACPICA upstream to help improving the release automation. The side effect of applying this patch in Linux is: 1. Some ACPICA initialization/termination APIs are no longer exported in Linux, these include: acpi_load_tables acpi_initialize_subsystem acpi_enable_subsystem acpi_initialize_objects acpi_terminate 2. This patch does not affect the following APIs as they are currently not marked with ACPI_EXPORT_SYMBOL in Linux: acpi_reallocate_root_table acpi_initialize_tables Such functions should not be exported as they are internal to ACPI subsystem in Linux, and will only be invoked inside of ACPI subsystem's initialization routines marked with __init and termination routines marked with __exit. While on other OSPMs, such functions may still need to be exported. Thus this patch adds the configurability for ACPICA, so that it leaves OSPMs to determine if the __init/__exit marked functions should be exported or not. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbxface.c | 7 ++++++- drivers/acpi/acpica/tbxfload.c | 2 +- drivers/acpi/acpica/utxface.c | 2 +- drivers/acpi/acpica/utxfinit.c | 9 ++++++--- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index bbaad5c4e2cd..7e63090742dc 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -148,6 +148,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) + /******************************************************************************* * * FUNCTION: acpi_reallocate_root_table @@ -182,6 +184,8 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table) + /******************************************************************************* * * FUNCTION: acpi_get_table_header @@ -357,6 +361,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } + ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status @@ -368,6 +373,7 @@ acpi_get_table(char *signature, return acpi_get_table_with_size(signature, instance, out_table, &tbl_size); } + ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* @@ -425,7 +431,6 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) - /******************************************************************************* * * FUNCTION: acpi_install_table_handler diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 5a2202495b0f..b1e1edd5703a 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -83,7 +83,7 @@ acpi_status acpi_load_tables(void) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_load_tables) +ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables) /******************************************************************************* * diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 2178da8af1a7..891a37b69d3c 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -105,7 +105,7 @@ acpi_status acpi_terminate(void) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_terminate) +ACPI_EXPORT_SYMBOL_INIT(acpi_terminate) #ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index dda18e622a93..ff6f4d194136 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -125,7 +125,8 @@ acpi_status acpi_initialize_subsystem(void) ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem) + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem) /******************************************************************************* * @@ -229,7 +230,8 @@ acpi_status acpi_enable_subsystem(u32 flags) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) + +ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem) /******************************************************************************* * @@ -315,4 +317,5 @@ acpi_status acpi_initialize_objects(u32 flags) acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_initialize_objects) + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_objects) -- cgit v1.2.3 From cd27d79f56e77924b6c66fa4a48306209b93605f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:22 +0800 Subject: ACPICA: Fix indentation issues for macro invocations. During the automatic translation of the upstream ACPICA source code into Linux kernel source code some extra white spaces are added by the "indent" program at the beginning of each line which is an invocation of a macro and there is no ";" at the end of the line. For this reason, a new mode has been added to the translation scripts to remove the extra spaces inserted before invoking such macros and add an empty line between the invocations of such macros (like the other function declarations). This new mode is executed after executing "indent" during the Linux release process. Consequently, some existing ACPICA source code in the Linux kernel tree needs to be adjusted to allow the new scripts to work correctly. The affected macros and files are: 1. ACPI_HW_DEPENDENT_RETURN (acpixf.h/acdebug.h/acevents.h): This macro is used as a wrapper for hardware dependent APIs to offer a stub when the reduced hardware is configured during compilation. 2. ACPI_EXPORT_SYMBOL (utglobal.c): This macro is used by Linux to export symbols to be found by Linux modules. All such invocations are well formatted except those exported as global variables. This can help to reduce the source code differences between Linux and upstream ACPICA, and also help to automate the release process. No functional or binary generation changes should result from it. Lv Zheng. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 3 ++- drivers/acpi/acpica/acevents.h | 3 ++- drivers/acpi/acpica/utcache.c | 2 +- drivers/acpi/acpica/utglobal.c | 3 +++ 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 57cdc770fba8..a9fd0b872062 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -113,7 +113,8 @@ void acpi_db_display_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) - ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) + +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) /* * dbconvert - miscellaneous conversion routines diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 3ae5fd02ae64..41abe552c7a3 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -71,7 +71,8 @@ acpi_status acpi_ev_init_global_lock_handler(void); ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_acquire_global_lock(u16 timeout)) - ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void)) + +ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void)) acpi_status acpi_ev_remove_global_lock_handler(void); /* diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c index a877a9647fd9..366bfec4b770 100644 --- a/drivers/acpi/acpica/utcache.c +++ b/drivers/acpi/acpica/utcache.c @@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utcache") acpi_status acpi_os_create_cache(char *cache_name, u16 object_size, - u16 max_depth, struct acpi_memory_list ** return_cache) + u16 max_depth, struct acpi_memory_list **return_cache) { struct acpi_memory_list *cache; diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 4f59784b397d..77caa4fbcdee 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -378,6 +378,9 @@ acpi_status acpi_ut_init_globals(void) /* Public globals */ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) + ACPI_EXPORT_SYMBOL(acpi_dbg_level) + ACPI_EXPORT_SYMBOL(acpi_dbg_layer) + ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) -- cgit v1.2.3 From bb42cc224a4626f9eaef34d9a334f0dc65133c40 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:29:49 +0800 Subject: ACPICA: Update default space handlers. This patch adds code that is already in ACPICA upstream, so applying it can help to reduce the source code differences between Linux and ACPICA upstream. This code fragment is only useful for ACPICA utilities and no functional changes to the Linux kernel should result from it. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exregion.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 303429bb4d5d..9d28867e60dc 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -400,6 +400,7 @@ acpi_ex_pci_config_space_handler(u32 function, switch (function) { case ACPI_READ: + *value = 0; status = acpi_os_read_pci_configuration(pci_id, pci_register, value, bit_width); break; -- cgit v1.2.3 From 99567bc5507bf404ae13a0c53264c921f380d06f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:04 +0800 Subject: ACPICA: Update check for setting the ANOBJ_IS_EXTERNAL flag. The ANOBJ_IS_EXTERNAL flag is only used by an ACPICA utilities - iASL. No functional change for the Linux kernel should results from applying this patch, but it helps to reduce source code differences between the kernel and ACPICA upstream. [rjw: Subject and changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nssearch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 5d43efc53a61..47420faef073 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -381,7 +381,8 @@ acpi_ns_search_and_enter(u32 target_name, /* Node is an object defined by an External() statement */ - if (flags & ACPI_NS_EXTERNAL) { + if (flags & ACPI_NS_EXTERNAL || + (walk_state && walk_state->opcode == AML_SCOPE_OP)) { new_node->flags |= ANOBJ_IS_EXTERNAL; } #endif -- cgit v1.2.3 From 98f7eb878a3495474f5d616301a914d7f9bdb389 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:10 +0800 Subject: ACPICA: Update namespace dump code. This patch merges namespace dump code updates from ACPICA upstream to reduce the source code differences between Linux and ACPICA upstream. No functional changes as currently nsdumpdv.c is not used by Linux. This patch does not affect the generation of the Linux kernel binary. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsdumpdv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 409ae80824d1..283762511b73 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -69,6 +69,7 @@ static acpi_status acpi_ns_dump_one_device(acpi_handle obj_handle, u32 level, void *context, void **return_value) { + struct acpi_buffer buffer; struct acpi_device_info *info; acpi_status status; u32 i; @@ -78,15 +79,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); - status = acpi_get_object_info(obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(obj_handle, &buffer); if (ACPI_SUCCESS(status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.string, + info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); ACPI_FREE(info); -- cgit v1.2.3 From 9187a415fd119c1d89a5ad2fd05513cd43699ebf Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:28 +0800 Subject: ACPICA: Add new statistics interface. This patch ports new counters and statistics interface, already implemented in ACPICA upstream, to Linux. That helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 2 ++ drivers/acpi/acpica/dsmethod.c | 1 + drivers/acpi/acpica/evsci.c | 1 + drivers/acpi/acpica/utglobal.c | 12 ++++++++++++ drivers/acpi/acpica/utxface.c | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 0fba431f4fcb..e9f1fc7f99c7 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -406,7 +406,9 @@ extern u32 acpi_gbl_nesting_level; /* Event counters */ +ACPI_EXTERN u32 acpi_method_count; ACPI_EXTERN u32 acpi_gpe_count; +ACPI_EXTERN u32 acpi_sci_count; ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; /* Support for dynamic control method tracing mechanism */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index df3ea125507f..81a78ba84311 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -292,6 +292,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; + acpi_method_count++; return_ACPI_STATUS(status); cleanup: diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 94d9ebddf575..9e9e3454d893 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -137,6 +137,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) interrupt_handled |= acpi_ev_sci_dispatch(); + acpi_sci_count++; return_UINT32(interrupt_handled); } diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 77caa4fbcdee..81f9a9584451 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -289,6 +289,16 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + /* Event counters */ + + acpi_method_count = 0; + acpi_sci_count = 0; + acpi_gpe_count = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_fixed_event_count[i] = 0; + } + #if (!ACPI_REDUCED_HARDWARE) /* GPE/SCI support */ @@ -383,4 +393,6 @@ ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_gpe_count) + ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 891a37b69d3c..39869022a417 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -208,6 +208,44 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ACPI_EXPORT_SYMBOL(acpi_get_system_info) +/******************************************************************************* + * + * FUNCTION: acpi_get_statistics + * + * PARAMETERS: stats - Where the statistics are returned + * + * RETURN: status - the status of the call + * + * DESCRIPTION: Get the contents of the various system counters + * + ******************************************************************************/ +acpi_status acpi_get_statistics(struct acpi_statistics *stats) +{ + ACPI_FUNCTION_TRACE(acpi_get_statistics); + + /* Parameter validation */ + + if (!stats) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Various interrupt-based event counters */ + + stats->sci_count = acpi_sci_count; + stats->gpe_count = acpi_gpe_count; + + ACPI_MEMCPY(stats->fixed_event_count, acpi_fixed_event_count, + sizeof(acpi_fixed_event_count)); + + /* Other counters */ + + stats->method_count = acpi_method_count; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_statistics) + /***************************************************************************** * * FUNCTION: acpi_install_initialization_handler -- cgit v1.2.3 From 130797a6c3f1421c10880a1681d6a9c57b80ef17 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:36 +0800 Subject: ACPICA: Fix wrong object length returned by acpi_ut_get_simple_object_size(). The object length returned by acpi_ut_get_simple_object_size() should be rounded up to the closest word boundary. This patch ports a fix from ACPICA upstream to Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utobject.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index aa61f66ee861..cddb0ef5b9b7 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -461,25 +461,28 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); + /* Start with the length of the (external) Acpi object */ + + length = sizeof(union acpi_object); + + /* A NULL object is allowed, can be a legal uninitialized package element */ + + if (!internal_object) { /* - * Handle a null object (Could be a uninitialized package - * element -- which is legal) + * Object is NULL, just return the length of union acpi_object + * (A NULL union acpi_object is an object of all zeroes.) */ - if (!internal_object) { - *obj_length = sizeof(union acpi_object); + *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(AE_OK); } - /* Start with the length of the Acpi object */ - - length = sizeof(union acpi_object); + /* A Namespace Node should never appear here */ if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { - /* Object is a named object (reference), just return the length */ + /* A namespace node should never get here */ - *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_AML_INTERNAL); } /* -- cgit v1.2.3 From bd48d677670bb35548718a1fd54c2c114a449973 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:42 +0800 Subject: ACPICA: Fix an ACPI_ALLOCATE_ZEROED() reversal. ACPI_FREE() should always be used to free objects allocated with ACPI_ALLOCATE_ZEROED(), so make acpi_ut_create_package_object() do that. This patch ports a fix from ACPICA upstream to Linux and helps to reduce source code differences between them. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index cddb0ef5b9b7..d2a7b6123743 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -180,7 +180,7 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count) package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + 1) * sizeof(void *)); if (!package_elements) { - acpi_ut_remove_reference(package_desc); + ACPI_FREE(package_desc); return_PTR(NULL); } -- cgit v1.2.3 From 6208a3dd370c73101d28d761f562723755108803 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:48 +0800 Subject: ACPICA: Cleanup useless memset invocations. This patch removes unnecessary memset() invocations where kmem_cache_zalloc() is used for allocating memory. It also helps to reduce source code differences between ACPICA upstream and Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utobject.c | 1 - drivers/acpi/acpica/utstate.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index d2a7b6123743..13e045025c33 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -396,7 +396,6 @@ void *acpi_ut_allocate_object_desc_dbg(const char *module_name, /* Mark the descriptor type */ - memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n", diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index a6b729d4c1dc..03c4c2febd84 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -161,7 +161,6 @@ union acpi_generic_state *acpi_ut_create_generic_state(void) if (state) { /* Initialize */ - memset(state, 0, sizeof(union acpi_generic_state)); state->common.descriptor_type = ACPI_DESC_TYPE_STATE; } -- cgit v1.2.3 From 2faa046485721c05ad3999bc6c8f6ced7017ef27 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:53 +0800 Subject: ACPICA: Remove dead AOPOBJ_INVALID check. Reversion commit 7cb7f45c7fee (Revert "ACPICA: Remove obsolete acpi_os_validate_address interface") restored a piece of dead code related to an obselete AOPOBJ_INVALID flag. Remove that code again. This helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exfldio.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 8ab01b613a18..49fb742d61b9 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -123,12 +123,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - /* * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear * address space and the request cannot be directly validated -- cgit v1.2.3 From dba47d3af92bb2e443cdb689422bf30b498bd209 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:00 +0800 Subject: ACPICA: Fix cached object deletion code. Function acpi_ut_delete_caches() is meant to be used to implement ACPI_ALLOCATE()/ACPI_FREE() mechanisms in ACPICA, so it should call acpi_os_free() rather than ACPI_FREE(). Linux is not affected by this issue as it uses kmem_cache instead of the ACPICA local cache, but the change helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utalloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index d84479610971..814267f52715 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -209,10 +209,10 @@ acpi_status acpi_ut_delete_caches(void) /* Free memory lists */ - ACPI_FREE(acpi_gbl_global_list); + acpi_os_free(acpi_gbl_global_list); acpi_gbl_global_list = NULL; - ACPI_FREE(acpi_gbl_ns_node_list); + acpi_os_free(acpi_gbl_ns_node_list); acpi_gbl_ns_node_list = NULL; #endif -- cgit v1.2.3 From 40bce100cafb945f1fb5475a70628b4379c74f38 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:18 +0800 Subject: ACPICA: Cleanup asmlinkage for ACPICA APIs. Add an asmlinkage wrapper around acpi_enter_sleep_state() to prevent an empty stub from being called by assmebly code for ACPI_REDUCED_HARDWARE set. As arch/x86/kernel/acpi/wakeup_xx.S is only compiled when CONFIG_ACPI=y and there are no users of ACPI_HARDWARE_REDUCED, currently this is in fact not a real issue, but a cleanup to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwxfsleep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 4895fca102dd..15dddc10fc9b 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -167,7 +167,7 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) +acpi_status acpi_enter_sleep_state_s4bios(void) { u32 in_value; acpi_status status; @@ -361,7 +361,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +acpi_status acpi_enter_sleep_state(u8 sleep_state) { acpi_status status; -- cgit v1.2.3 From 45c9f78b25ad9ce6cdf259ac4b652e6783adcb23 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:24 +0800 Subject: ACPICA: Add __init for ACPICA initializers/finalizers. This patch adds __init to the ACPICA documented initializers: acpi_initialize_tables() acpi_initialize_subsystem() acpi_load_tables() acpi_enable_subsystem() acpi_initialize_objects() and to acpi_reallocate_root_table(), acpi_find_root_pointer() which are also meant to be called only during initialization. This patch adds __init to the ACPICA documented finalizer: acpi_terminate() as this finalizer is only called in __init function now. This change helps to reduce source code differences between ACPICA upstream and Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbutils.c | 3 +-- drivers/acpi/acpica/tbxface.c | 2 +- drivers/acpi/acpica/tbxfload.c | 2 +- drivers/acpi/acpica/tbxfroot.c | 2 +- drivers/acpi/acpica/utxface.c | 2 +- drivers/acpi/acpica/utxfinit.c | 6 +++--- 6 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 43ffe21c7b26..3d6bb83aa7e7 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -430,8 +430,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * ******************************************************************************/ -acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address) +acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) { struct acpi_table_rsdp *rsdp; u32 table_entry_size; diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 7e63090742dc..db826eaadd1c 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -164,7 +164,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) * kernel. * ******************************************************************************/ -acpi_status acpi_reallocate_root_table(void) +acpi_status __init acpi_reallocate_root_table(void) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index b1e1edd5703a..60b5a871833c 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -66,7 +66,7 @@ static acpi_status acpi_tb_load_namespace(void); * ******************************************************************************/ -acpi_status acpi_load_tables(void) +acpi_status __init acpi_load_tables(void) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 1c95fabbe6a4..e4e1468877c3 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -111,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * ******************************************************************************/ -acpi_status acpi_find_root_pointer(acpi_size *table_address) +acpi_status __init acpi_find_root_pointer(acpi_size *table_address) { u8 *table_ptr; u8 *mem_rover; diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 39869022a417..be322c83643a 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -61,7 +61,7 @@ ACPI_MODULE_NAME("utxface") * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. * ******************************************************************************/ -acpi_status acpi_terminate(void) +acpi_status __init acpi_terminate(void) { acpi_status status; diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index ff6f4d194136..75efea0539c1 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utxfinit") * called, so any early initialization belongs here. * ******************************************************************************/ -acpi_status acpi_initialize_subsystem(void) +acpi_status __init acpi_initialize_subsystem(void) { acpi_status status; @@ -140,7 +140,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem) * Puts system into ACPI mode if it isn't already. * ******************************************************************************/ -acpi_status acpi_enable_subsystem(u32 flags) +acpi_status __init acpi_enable_subsystem(u32 flags) { acpi_status status = AE_OK; @@ -245,7 +245,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem) * objects and executing AML code for Regions, buffers, etc. * ******************************************************************************/ -acpi_status acpi_initialize_objects(u32 flags) +acpi_status __init acpi_initialize_objects(u32 flags) { acpi_status status = AE_OK; -- cgit v1.2.3 From 7ea6c6c15ee16f4c7f5eeaa62f77e696f85ae0d1 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 28 Oct 2013 14:06:55 -0700 Subject: Move cper.c from drivers/acpi/apei to drivers/firmware/efi cper.c contains code to decode and print "Common Platform Error Records". Originally added under drivers/acpi/apei because the only user was in that same directory - but now we have another consumer, and we shouldn't have to force CONFIG_ACPI_APEI get access to this code. Since CPER is defined in the UEFI specification - the logical home for this code is under drivers/firmware/efi/ Acked-by: Matt Fleming Acked-by: Ingo Molnar Signed-off-by: Tony Luck --- drivers/acpi/Kconfig | 4 +- drivers/acpi/apei/Kconfig | 2 + drivers/acpi/apei/Makefile | 2 +- drivers/acpi/apei/cper.c | 410 --------------------------------------------- 4 files changed, 6 insertions(+), 412 deletions(-) delete mode 100644 drivers/acpi/apei/cper.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 252f0e818a49..08eadb4a57cb 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -374,7 +374,9 @@ source "drivers/acpi/apei/Kconfig" config ACPI_EXTLOG tristate "Extended Error Log support" - depends on X86_MCE && ACPI_APEI + depends on X86_MCE + select EFI + select UEFI_CPER default n help Certain usages such as Predictive Failure Analysis (PFA) require diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index f0c1ce95a0ec..786294bb682c 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -2,6 +2,8 @@ config ACPI_APEI bool "ACPI Platform Error Interface (APEI)" select MISC_FILESYSTEMS select PSTORE + select EFI + select UEFI_CPER depends on X86 help APEI allows to report errors (for example from the chipset) diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile index d1d1bc0a4ee1..5d575a955940 100644 --- a/drivers/acpi/apei/Makefile +++ b/drivers/acpi/apei/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o -apei-y := apei-base.o hest.o cper.o erst.o +apei-y := apei-base.o hest.o erst.o diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c deleted file mode 100644 index 1491dd4f08f9..000000000000 --- a/drivers/acpi/apei/cper.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * UEFI Common Platform Error Record (CPER) support - * - * Copyright (C) 2010, Intel Corp. - * Author: Huang Ying - * - * CPER is the format used to describe platform hardware error by - * various tables, such as ERST, BERT and HEST etc. - * - * For more information about CPER, please refer to Appendix N of UEFI - * Specification version 2.4. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define INDENT_SP " " -/* - * CPER record ID need to be unique even after reboot, because record - * ID is used as index for ERST storage, while CPER records from - * multiple boot may co-exist in ERST. - */ -u64 cper_next_record_id(void) -{ - static atomic64_t seq; - - if (!atomic64_read(&seq)) - atomic64_set(&seq, ((u64)get_seconds()) << 32); - - return atomic64_inc_return(&seq); -} -EXPORT_SYMBOL_GPL(cper_next_record_id); - -static const char *cper_severity_strs[] = { - "recoverable", - "fatal", - "corrected", - "info", -}; - -static const char *cper_severity_str(unsigned int severity) -{ - return severity < ARRAY_SIZE(cper_severity_strs) ? - cper_severity_strs[severity] : "unknown"; -} - -/* - * cper_print_bits - print strings for set bits - * @pfx: prefix for each line, including log level and prefix string - * @bits: bit mask - * @strs: string array, indexed by bit position - * @strs_size: size of the string array: @strs - * - * For each set bit in @bits, print the corresponding string in @strs. - * If the output length is longer than 80, multiple line will be - * printed, with @pfx is printed at the beginning of each line. - */ -void cper_print_bits(const char *pfx, unsigned int bits, - const char * const strs[], unsigned int strs_size) -{ - int i, len = 0; - const char *str; - char buf[84]; - - for (i = 0; i < strs_size; i++) { - if (!(bits & (1U << i))) - continue; - str = strs[i]; - if (!str) - continue; - if (len && len + strlen(str) + 2 > 80) { - printk("%s\n", buf); - len = 0; - } - if (!len) - len = snprintf(buf, sizeof(buf), "%s%s", pfx, str); - else - len += snprintf(buf+len, sizeof(buf)-len, ", %s", str); - } - if (len) - printk("%s\n", buf); -} - -static const char * const cper_proc_type_strs[] = { - "IA32/X64", - "IA64", -}; - -static const char * const cper_proc_isa_strs[] = { - "IA32", - "IA64", - "X64", -}; - -static const char * const cper_proc_error_type_strs[] = { - "cache error", - "TLB error", - "bus error", - "micro-architectural error", -}; - -static const char * const cper_proc_op_strs[] = { - "unknown or generic", - "data read", - "data write", - "instruction execution", -}; - -static const char * const cper_proc_flag_strs[] = { - "restartable", - "precise IP", - "overflow", - "corrected", -}; - -static void cper_print_proc_generic(const char *pfx, - const struct cper_sec_proc_generic *proc) -{ - if (proc->validation_bits & CPER_PROC_VALID_TYPE) - printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type, - proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ? - cper_proc_type_strs[proc->proc_type] : "unknown"); - if (proc->validation_bits & CPER_PROC_VALID_ISA) - printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa, - proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ? - cper_proc_isa_strs[proc->proc_isa] : "unknown"); - if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { - printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); - cper_print_bits(pfx, proc->proc_error_type, - cper_proc_error_type_strs, - ARRAY_SIZE(cper_proc_error_type_strs)); - } - if (proc->validation_bits & CPER_PROC_VALID_OPERATION) - printk("%s""operation: %d, %s\n", pfx, proc->operation, - proc->operation < ARRAY_SIZE(cper_proc_op_strs) ? - cper_proc_op_strs[proc->operation] : "unknown"); - if (proc->validation_bits & CPER_PROC_VALID_FLAGS) { - printk("%s""flags: 0x%02x\n", pfx, proc->flags); - cper_print_bits(pfx, proc->flags, cper_proc_flag_strs, - ARRAY_SIZE(cper_proc_flag_strs)); - } - if (proc->validation_bits & CPER_PROC_VALID_LEVEL) - printk("%s""level: %d\n", pfx, proc->level); - if (proc->validation_bits & CPER_PROC_VALID_VERSION) - printk("%s""version_info: 0x%016llx\n", pfx, proc->cpu_version); - if (proc->validation_bits & CPER_PROC_VALID_ID) - printk("%s""processor_id: 0x%016llx\n", pfx, proc->proc_id); - if (proc->validation_bits & CPER_PROC_VALID_TARGET_ADDRESS) - printk("%s""target_address: 0x%016llx\n", - pfx, proc->target_addr); - if (proc->validation_bits & CPER_PROC_VALID_REQUESTOR_ID) - printk("%s""requestor_id: 0x%016llx\n", - pfx, proc->requestor_id); - if (proc->validation_bits & CPER_PROC_VALID_RESPONDER_ID) - printk("%s""responder_id: 0x%016llx\n", - pfx, proc->responder_id); - if (proc->validation_bits & CPER_PROC_VALID_IP) - printk("%s""IP: 0x%016llx\n", pfx, proc->ip); -} - -static const char *cper_mem_err_type_strs[] = { - "unknown", - "no error", - "single-bit ECC", - "multi-bit ECC", - "single-symbol chipkill ECC", - "multi-symbol chipkill ECC", - "master abort", - "target abort", - "parity error", - "watchdog timeout", - "invalid address", - "mirror Broken", - "memory sparing", - "scrub corrected error", - "scrub uncorrected error", - "physical memory map-out event", -}; - -static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) -{ - if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) - printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); - if (mem->validation_bits & CPER_MEM_VALID_PA) - printk("%s""physical_address: 0x%016llx\n", - pfx, mem->physical_addr); - if (mem->validation_bits & CPER_MEM_VALID_PA_MASK) - printk("%s""physical_address_mask: 0x%016llx\n", - pfx, mem->physical_addr_mask); - if (mem->validation_bits & CPER_MEM_VALID_NODE) - pr_debug("node: %d\n", mem->node); - if (mem->validation_bits & CPER_MEM_VALID_CARD) - pr_debug("card: %d\n", mem->card); - if (mem->validation_bits & CPER_MEM_VALID_MODULE) - pr_debug("module: %d\n", mem->module); - if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) - pr_debug("rank: %d\n", mem->rank); - if (mem->validation_bits & CPER_MEM_VALID_BANK) - pr_debug("bank: %d\n", mem->bank); - if (mem->validation_bits & CPER_MEM_VALID_DEVICE) - pr_debug("device: %d\n", mem->device); - if (mem->validation_bits & CPER_MEM_VALID_ROW) - pr_debug("row: %d\n", mem->row); - if (mem->validation_bits & CPER_MEM_VALID_COLUMN) - pr_debug("column: %d\n", mem->column); - if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) - pr_debug("bit_position: %d\n", mem->bit_pos); - if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) - pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id); - if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) - pr_debug("responder_id: 0x%016llx\n", mem->responder_id); - if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) - pr_debug("target_id: 0x%016llx\n", mem->target_id); - if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { - u8 etype = mem->error_type; - printk("%s""error_type: %d, %s\n", pfx, etype, - etype < ARRAY_SIZE(cper_mem_err_type_strs) ? - cper_mem_err_type_strs[etype] : "unknown"); - } - if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) { - const char *bank = NULL, *device = NULL; - dmi_memdev_name(mem->mem_dev_handle, &bank, &device); - if (bank != NULL && device != NULL) - printk("%s""DIMM location: %s %s", pfx, bank, device); - else - printk("%s""DIMM DMI handle: 0x%.4x", - pfx, mem->mem_dev_handle); - } -} - -static const char *cper_pcie_port_type_strs[] = { - "PCIe end point", - "legacy PCI end point", - "unknown", - "unknown", - "root port", - "upstream switch port", - "downstream switch port", - "PCIe to PCI/PCI-X bridge", - "PCI/PCI-X to PCIe bridge", - "root complex integrated endpoint device", - "root complex event collector", -}; - -static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, - const struct acpi_generic_data *gdata) -{ - if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) - printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, - pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? - cper_pcie_port_type_strs[pcie->port_type] : "unknown"); - if (pcie->validation_bits & CPER_PCIE_VALID_VERSION) - printk("%s""version: %d.%d\n", pfx, - pcie->version.major, pcie->version.minor); - if (pcie->validation_bits & CPER_PCIE_VALID_COMMAND_STATUS) - printk("%s""command: 0x%04x, status: 0x%04x\n", pfx, - pcie->command, pcie->status); - if (pcie->validation_bits & CPER_PCIE_VALID_DEVICE_ID) { - const __u8 *p; - printk("%s""device_id: %04x:%02x:%02x.%x\n", pfx, - pcie->device_id.segment, pcie->device_id.bus, - pcie->device_id.device, pcie->device_id.function); - printk("%s""slot: %d\n", pfx, - pcie->device_id.slot >> CPER_PCIE_SLOT_SHIFT); - printk("%s""secondary_bus: 0x%02x\n", pfx, - pcie->device_id.secondary_bus); - printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx, - pcie->device_id.vendor_id, pcie->device_id.device_id); - p = pcie->device_id.class_code; - printk("%s""class_code: %02x%02x%02x\n", pfx, p[0], p[1], p[2]); - } - if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER) - printk("%s""serial number: 0x%04x, 0x%04x\n", pfx, - pcie->serial_number.lower, pcie->serial_number.upper); - if (pcie->validation_bits & CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS) - printk( - "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", - pfx, pcie->bridge.secondary_status, pcie->bridge.control); -} - -static void cper_estatus_print_section( - const char *pfx, const struct acpi_generic_data *gdata, int sec_no) -{ - uuid_le *sec_type = (uuid_le *)gdata->section_type; - __u16 severity; - char newpfx[64]; - - severity = gdata->error_severity; - printk("%s""Error %d, type: %s\n", pfx, sec_no, - cper_severity_str(severity)); - if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) - printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); - if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) - printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); - - snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); - if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { - struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); - printk("%s""section_type: general processor error\n", newpfx); - if (gdata->error_data_length >= sizeof(*proc_err)) - cper_print_proc_generic(newpfx, proc_err); - else - goto err_section_too_small; - } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { - struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); - printk("%s""section_type: memory error\n", newpfx); - if (gdata->error_data_length >= sizeof(*mem_err)) - cper_print_mem(newpfx, mem_err); - else - goto err_section_too_small; - } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { - struct cper_sec_pcie *pcie = (void *)(gdata + 1); - printk("%s""section_type: PCIe error\n", newpfx); - if (gdata->error_data_length >= sizeof(*pcie)) - cper_print_pcie(newpfx, pcie, gdata); - else - goto err_section_too_small; - } else - printk("%s""section type: unknown, %pUl\n", newpfx, sec_type); - - return; - -err_section_too_small: - pr_err(FW_WARN "error section length is too small\n"); -} - -void cper_estatus_print(const char *pfx, - const struct acpi_generic_status *estatus) -{ - struct acpi_generic_data *gdata; - unsigned int data_len, gedata_len; - int sec_no = 0; - char newpfx[64]; - __u16 severity; - - severity = estatus->error_severity; - if (severity == CPER_SEV_CORRECTED) - printk("%s%s\n", pfx, - "It has been corrected by h/w " - "and requires no further action"); - printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); - data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); - snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); - while (data_len >= sizeof(*gdata)) { - gedata_len = gdata->error_data_length; - cper_estatus_print_section(newpfx, gdata, sec_no); - data_len -= gedata_len + sizeof(*gdata); - gdata = (void *)(gdata + 1) + gedata_len; - sec_no++; - } -} -EXPORT_SYMBOL_GPL(cper_estatus_print); - -int cper_estatus_check_header(const struct acpi_generic_status *estatus) -{ - if (estatus->data_length && - estatus->data_length < sizeof(struct acpi_generic_data)) - return -EINVAL; - if (estatus->raw_data_length && - estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) - return -EINVAL; - - return 0; -} -EXPORT_SYMBOL_GPL(cper_estatus_check_header); - -int cper_estatus_check(const struct acpi_generic_status *estatus) -{ - struct acpi_generic_data *gdata; - unsigned int data_len, gedata_len; - int rc; - - rc = cper_estatus_check_header(estatus); - if (rc) - return rc; - data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); - while (data_len >= sizeof(*gdata)) { - gedata_len = gdata->error_data_length; - if (gedata_len > data_len - sizeof(*gdata)) - return -EINVAL; - data_len -= gedata_len + sizeof(*gdata); - gdata = (void *)(gdata + 1) + gedata_len; - } - if (data_len) - return -EINVAL; - - return 0; -} -EXPORT_SYMBOL_GPL(cper_estatus_check); -- cgit v1.2.3 From f0eb2e5dc06f5e100d59bb49a823f9a294e82db7 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Tue, 5 Nov 2013 01:20:42 -0600 Subject: ACPI / blacklist: fix name of ThinkPad Edge E530 That is the advertised name. http://shop.lenovo.com/us/en/laptops/thinkpad/edge-series/e530/ Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index b7fd1aeb6c42..fb848378d582 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -304,7 +304,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { .callback = dmi_disable_osi_win8, - .ident = "Lenovo ThinkPad Edge E530", + .ident = "ThinkPad Edge E530", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), -- cgit v1.2.3 From 71bba8fafac8975dbb684df4098d2dd6baac1fda Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:40:50 +0100 Subject: ACPI: Remove acpi_pci_slot_init() headers from internal.h Since acpi_pci_slot_init() is now called from acpi_pci_init() and pci-acpi.h contains its header, remove that header (and the empty definition of that function for CONFIG_ACPI_PCI_SLOT unset) from internal.h as it doesn't have to be there any more. That also avoids a build warning about duplicate function definitions for CONFIG_ACPI_PCI_SLOT unset. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/internal.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 20f423337e1f..ebc3ad0a188d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -26,11 +26,6 @@ acpi_status acpi_os_initialize1(void); int init_acpi_device_notify(void); int acpi_scan_init(void); -#ifdef CONFIG_ACPI_PCI_SLOT -void acpi_pci_slot_init(void); -#else -static inline void acpi_pci_slot_init(void) { } -#endif void acpi_pci_root_init(void); void acpi_pci_link_init(void); void acpi_pci_root_hp_init(void); -- cgit v1.2.3 From 6931007cc90ba94b3c2b29179d0a7cde194dabe8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:01 +0100 Subject: ACPI / scan: Start matching drivers after trying scan handlers ACPI scan handlers should always be attached to struct acpi_device objects before any ACPI drivers, but there is a window during which a driver may be attached to a struct acpi_device before checking if there is a matching scan handler. Namely, that will happen if an ACPI driver module is loaded during acpi_bus_scan() right after the first namespace walk is complete and before the given device is processed by the second namespace walk. To prevent that from happening, set the match_driver flags of struct acpi_device objects right before running device_attach() for them in acpi_bus_device_attach(). Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fbdb82e70d10..4d377a22622a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1677,7 +1677,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, void acpi_device_add_finalize(struct acpi_device *device) { - device->flags.match_driver = true; dev_set_uevent_suppress(&device->dev, false); kobject_uevent(&device->dev.kobj, KOBJ_ADD); } @@ -1916,8 +1915,12 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, return AE_OK; ret = acpi_scan_attach_handler(device); - if (ret) - return ret > 0 ? AE_OK : AE_CTRL_DEPTH; + if (ret < 0) + return AE_CTRL_DEPTH; + + device->flags.match_driver = true; + if (ret > 0) + return AE_OK; ret = device_attach(&device->dev); return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; -- cgit v1.2.3 From 7f28ddeccea453fd20b1c74a88df19590ad9203c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:14 +0100 Subject: ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug In theory, an ACPI device object may be the parent of another device object whose hotplug is disabled by user space through its scan handler. In that case, the eject operation targeting the parent should fail as though the parent's own hotplug was disabled, but currently this is not the case, because acpi_scan_hot_remove() doesn't check the disable/enable hotplug status of the children of the top-most object passed to it. To fix this, modify acpi_bus_offline_companions() to return an error code if hotplug is disabled for the given device object. [Also change the name of the function to acpi_bus_offline(), because it is not only about companions any more, and change the name of acpi_bus_online_companions() accordingly.] Make acpi_scan_hot_remove() propagate that error to its callers. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 57 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 21 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4d377a22622a..9bdcc187bf4b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, if (acpi_bus_get_device(handle, &device)) return AE_OK; + if (device->handler && !device->handler->hotplug.enabled) { + *ret_p = &device->dev; + return AE_SUPPORT; + } + mutex_lock(&device->physical_node_lock); list_for_each_entry(pn, &device->physical_node_list, node) { @@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, return status; } -static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) * If the first pass is successful, the second one isn't needed, though. */ errdev = NULL; - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)false, (void **)&errdev); - acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); + status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + NULL, acpi_bus_offline, (void *)false, + (void **)&errdev); + if (status == AE_SUPPORT) { + dev_warn(errdev, "Offline disabled.\n"); + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_online, NULL, NULL, NULL); + put_device(&device->dev); + return -EPERM; + } + acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); if (errdev) { errdev = NULL; acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)true , (void **)&errdev); + NULL, acpi_bus_offline, (void *)true, + (void **)&errdev); if (!errdev || acpi_force_hot_remove) - acpi_bus_offline_companions(handle, 0, (void *)true, - (void **)&errdev); + acpi_bus_offline(handle, 0, (void *)true, + (void **)&errdev); if (errdev && !acpi_force_hot_remove) { dev_warn(errdev, "Offline failed.\n"); - acpi_bus_online_companions(handle, 0, NULL, NULL); + acpi_bus_online(handle, 0, NULL, NULL); acpi_walk_namespace(ACPI_TYPE_ANY, handle, - ACPI_UINT32_MAX, - acpi_bus_online_companions, NULL, - NULL, NULL); + ACPI_UINT32_MAX, acpi_bus_online, + NULL, NULL, NULL); put_device(&device->dev); return -EBUSY; } @@ -290,10 +301,9 @@ static void acpi_bus_device_eject(void *context) goto err_out; handler = device->handler; - if (!handler || !handler->hotplug.enabled) { - ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - goto err_out; - } + if (!handler || !handler->hotplug.enabled) + goto err_support; + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); if (handler->hotplug.mode == AHM_CONTAINER) @@ -301,14 +311,19 @@ static void acpi_bus_device_eject(void *context) get_device(&device->dev); error = acpi_scan_hot_remove(device); - if (error) + if (error == -EPERM) { + goto err_support; + } else if (error) { goto err_out; + } out: mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); return; + err_support: + ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; err_out: acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, NULL); -- cgit v1.2.3 From 2441191a19039002b2c454a261fb45986df15184 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:27 +0100 Subject: ACPI / hotplug: Fix handle_root_bridge_removal() It is required to do get_device() on the struct acpi_device in question before passing it to acpi_bus_hot_remove_device() through acpi_os_hotplug_execute(), because acpi_bus_hot_remove_device() calls acpi_scan_hot_remove() that does put_device() on that object. The ACPI PCI root removal routine, handle_root_bridge_removal(), doesn't do that, which may lead to premature freeing of the device object or to executing put_device() on an object that has been freed already. Fix this problem by making handle_root_bridge_removal() use get_device() as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani Cc: All applicable --- drivers/acpi/pci_root.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f425653..d7e53ea53d6c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -608,9 +608,12 @@ static void handle_root_bridge_removal(struct acpi_device *device) ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + get_device(&device->dev); status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + put_device(&device->dev); kfree(ej_event); + } } static void _handle_hotplug_event_root(struct work_struct *work) -- cgit v1.2.3 From 5add99cfef416487d32b4b7075fe1a409f3a5e82 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:39 +0100 Subject: ACPI / hotplug: Simplify device ejection routines Simplify handle_root_bridge_removal() and acpi_eject_store() by getting rid of struct acpi_eject_event and passing device objects directly to async routines executed via acpi_os_hotplug_execute(). Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/pci_root.c | 20 ++------------------ drivers/acpi/scan.c | 46 ++++++++++++++++++---------------------------- 2 files changed, 20 insertions(+), 46 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d7e53ea53d6c..2c03aaee1006 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -593,27 +593,11 @@ static void handle_root_bridge_insertion(acpi_handle handle) static void handle_root_bridge_removal(struct acpi_device *device) { acpi_status status; - struct acpi_eject_event *ej_event; - - ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); - if (!ej_event) { - /* Inform firmware the hot-remove operation has error */ - (void) acpi_evaluate_hotplug_ost(device->handle, - ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); - return; - } - - ej_event->device = device; - ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; get_device(&device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); - if (ACPI_FAILURE(status)) { + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, device); + if (ACPI_FAILURE(status)) put_device(&device->dev); - kfree(ej_event); - } } static void _handle_hotplug_event_root(struct work_struct *work) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9bdcc187bf4b..cc19d623a18f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -441,18 +441,8 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) NULL); } -/** - * acpi_bus_hot_remove_device: hot-remove a device and its children - * @context: struct acpi_eject_event pointer (freed in this func) - * - * Hot-remove a device and its children. This function frees up the - * memory space passed by arg context, so that the caller may call - * this function asynchronously through acpi_os_hotplug_execute(). - */ -void acpi_bus_hot_remove_device(void *context) +void __acpi_bus_hot_remove_device(struct acpi_device *device, u32 ost_src) { - struct acpi_eject_event *ej_event = context; - struct acpi_device *device = ej_event->device; acpi_handle handle = device->handle; int error; @@ -461,13 +451,21 @@ void acpi_bus_hot_remove_device(void *context) error = acpi_scan_hot_remove(device); if (error && handle) - acpi_evaluate_hotplug_ost(handle, ej_event->event, + acpi_evaluate_hotplug_ost(handle, ost_src, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); - kfree(context); +} + +/** + * acpi_bus_hot_remove_device: Hot-remove a device and its children. + * @context: Address of the ACPI device object to hot-remove. + */ +void acpi_bus_hot_remove_device(void *context) +{ + __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); } EXPORT_SYMBOL(acpi_bus_hot_remove_device); @@ -497,15 +495,18 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); +static void acpi_eject_store_work(void *context) +{ + __acpi_bus_hot_remove_device(context, ACPI_OST_EC_OSPM_EJECT); +} + static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct acpi_device *acpi_device = to_acpi_device(d); - struct acpi_eject_event *ej_event; acpi_object_type not_used; acpi_status status; - int ret; if (!count || buf[0] != '1') return -EINVAL; @@ -518,28 +519,17 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) return -ENODEV; - ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); - if (!ej_event) { - ret = -ENOMEM; - goto err_out; - } acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - ej_event->device = acpi_device; - ej_event->event = ACPI_OST_EC_OSPM_EJECT; get_device(&acpi_device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); + status = acpi_os_hotplug_execute(acpi_eject_store_work, acpi_device); if (ACPI_SUCCESS(status)) return count; put_device(&acpi_device->dev); - kfree(ej_event); - ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; - - err_out: acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); - return ret; + return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; } static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); -- cgit v1.2.3 From ace8238b00eafd493b8dbcc7db813ed72b8b6e87 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:48 +0100 Subject: ACPI / hotplug: Make acpi_bus_hot_remove_device() internal Notice that handle_root_bridge_removal() is the only user of acpi_bus_hot_remove_device(), so it doesn't have to be exported any more and can be made internal to the ACPI core. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/internal.h | 1 + drivers/acpi/pci_root.c | 2 ++ drivers/acpi/scan.c | 1 - 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ebc3ad0a188d..6c79ae69d344 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,6 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); +void acpi_bus_hot_remove_device(void *context); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 2c03aaee1006..add408b07c93 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -39,6 +39,8 @@ #include #include +#include "internal.h" + #define PREFIX "ACPI: " #define _COMPONENT ACPI_PCI_COMPONENT diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index cc19d623a18f..1217ba33f8bf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -467,7 +467,6 @@ void acpi_bus_hot_remove_device(void *context) { __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); } -EXPORT_SYMBOL(acpi_bus_hot_remove_device); static ssize_t real_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3 From a3b1b1ef78cd2ffb5d3a223465064dee05929dc3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:58 +0100 Subject: ACPI / hotplug: Merge device hot-removal routines There is no real reasn why acpi_bus_device_eject() and acpi_bus_hot_remove_device() should work differently, so rework acpi_bus_device_eject() so that it can be called internally by both acpi_bus_hot_remove_device() and acpi_eject_store_work(). Accordingly, rework acpi_hotplug_notify_cb() to queue up the execution of acpi_bus_hot_remove_device() through acpi_os_hotplug_execute() on eject request notifications. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 84 ++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1217ba33f8bf..4a0a591feed3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,10 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static void acpi_bus_device_eject(void *context) +static void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) { - acpi_handle handle = context; - struct acpi_device *device = NULL; + acpi_handle handle = device->handle; struct acpi_scan_handler *handler; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; @@ -296,20 +295,19 @@ static void acpi_bus_device_eject(void *context) lock_device_hotplug(); mutex_lock(&acpi_scan_lock); - acpi_bus_get_device(handle, &device); - if (!device) - goto err_out; - handler = device->handler; - if (!handler || !handler->hotplug.enabled) + if (!handler || !handler->hotplug.enabled) { + put_device(&device->dev); goto err_support; + } + + if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); if (handler->hotplug.mode == AHM_CONTAINER) kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - get_device(&device->dev); error = acpi_scan_hot_remove(device); if (error == -EPERM) { goto err_support; @@ -325,8 +323,7 @@ static void acpi_bus_device_eject(void *context) err_support: ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; err_out: - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, - NULL); + acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); goto out; } @@ -408,10 +405,20 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); } +/** + * acpi_bus_hot_remove_device: Hot-remove a device and its children. + * @context: Address of the ACPI device object to hot-remove. + */ +void acpi_bus_hot_remove_device(void *context) +{ + acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); +} + static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { acpi_osd_exec_callback callback; struct acpi_scan_handler *handler = data; + struct acpi_device *adev; acpi_status status; if (!handler->hotplug.enabled) @@ -428,44 +435,29 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); - callback = acpi_bus_device_eject; - break; + status = acpi_bus_get_device(handle, &adev); + if (ACPI_FAILURE(status)) + goto err_out; + + get_device(&adev->dev); + callback = acpi_bus_hot_remove_device; + status = acpi_os_hotplug_execute(callback, adev); + if (ACPI_SUCCESS(status)) + return; + + put_device(&adev->dev); + goto err_out; default: /* non-hotplug event; possibly handled by other handler */ return; } status = acpi_os_hotplug_execute(callback, handle); - if (ACPI_FAILURE(status)) - acpi_evaluate_hotplug_ost(handle, type, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); -} - -void __acpi_bus_hot_remove_device(struct acpi_device *device, u32 ost_src) -{ - acpi_handle handle = device->handle; - int error; - - lock_device_hotplug(); - mutex_lock(&acpi_scan_lock); - - error = acpi_scan_hot_remove(device); - if (error && handle) - acpi_evaluate_hotplug_ost(handle, ost_src, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); - - mutex_unlock(&acpi_scan_lock); - unlock_device_hotplug(); -} + if (ACPI_SUCCESS(status)) + return; -/** - * acpi_bus_hot_remove_device: Hot-remove a device and its children. - * @context: Address of the ACPI device object to hot-remove. - */ -void acpi_bus_hot_remove_device(void *context) -{ - __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); + err_out: + acpi_evaluate_hotplug_ost(handle, type, + ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); } static ssize_t real_power_state_show(struct device *dev, @@ -496,7 +488,7 @@ static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); static void acpi_eject_store_work(void *context) { - __acpi_bus_hot_remove_device(context, ACPI_OST_EC_OSPM_EJECT); + acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT); } static ssize_t -- cgit v1.2.3 From 43d388832bd3e413e9b5e6f3caef4b0844b901af Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:42:09 +0100 Subject: ACPI / hotplug: Carry out PCI root eject directly Since _handle_hotplug_event_root() is run from the ACPI hotplug workqueue, it doesn't need to queue up a work item to eject a PCI host bridge on the same workqueue. Instead, it can just carry out the eject by calling acpi_bus_device_eject() directly, so make that happen. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/internal.h | 2 +- drivers/acpi/pci_root.c | 24 ++++++++++-------------- drivers/acpi/scan.c | 4 ++-- 3 files changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 6c79ae69d344..80cd1a10c4c3 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,7 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_bus_hot_remove_device(void *context); +void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index add408b07c93..d77f0bf7eda0 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -592,16 +592,6 @@ static void handle_root_bridge_insertion(acpi_handle handle) acpi_handle_err(handle, "cannot add bridge to acpi list\n"); } -static void handle_root_bridge_removal(struct acpi_device *device) -{ - acpi_status status; - - get_device(&device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, device); - if (ACPI_FAILURE(status)) - put_device(&device->dev); -} - static void _handle_hotplug_event_root(struct work_struct *work) { struct acpi_pci_root *root; @@ -612,6 +602,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) hp_work = container_of(work, struct acpi_hp_work, work); handle = hp_work->handle; type = hp_work->type; + kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ acpi_scan_lock_acquire(); @@ -641,9 +632,15 @@ static void _handle_hotplug_event_root(struct work_struct *work) /* request device eject */ acpi_handle_printk(KERN_DEBUG, handle, "Device eject notify on %s\n", __func__); - if (root) - handle_root_bridge_removal(root->device); - break; + if (!root) + break; + + get_device(&root->device->dev); + + acpi_scan_lock_release(); + + acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); + return; default: acpi_handle_warn(handle, "notify_handler: unknown event type 0x%x\n", @@ -652,7 +649,6 @@ static void _handle_hotplug_event_root(struct work_struct *work) } acpi_scan_lock_release(); - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } static void handle_hotplug_event_root(acpi_handle handle, u32 type, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4a0a591feed3..c7317fe213bf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,7 +285,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) +void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) { acpi_handle handle = device->handle; struct acpi_scan_handler *handler; @@ -409,7 +409,7 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) * acpi_bus_hot_remove_device: Hot-remove a device and its children. * @context: Address of the ACPI device object to hot-remove. */ -void acpi_bus_hot_remove_device(void *context) +static void acpi_bus_hot_remove_device(void *context) { acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); } -- cgit v1.2.3 From 176a88d79d6b5aebabaff16734e8b3107efcaaad Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:42:17 +0100 Subject: ACPI / hotplug: Do not execute "insert in progress" _OST According to the ACPI spec (5.0, Section 6.3.5), the "Device insertion in progress (pending)" (0x80) _OST status code is reserved for the "Insertion Processing" (0x200) source event which is "a result of an OSPM action". Specifically, it is not a notification, so that status code should not be used during notification processing, which unfortunately is done by acpi_scan_bus_device_check(). For this reason, drop the ACPI_OST_SC_INSERT_IN_PROGRESS _OST status evaluation from there (it was a mistake to put it in there in the first place). Signed-off-by: Rafael J. Wysocki Cc: All applicable --- drivers/acpi/scan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c7317fe213bf..5cd7f8c5666a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -343,8 +343,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) goto out; } } - acpi_evaluate_hotplug_ost(handle, ost_source, - ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); error = acpi_bus_scan(handle); if (error) { acpi_handle_warn(handle, "Namespace scan failure\n"); -- cgit v1.2.3 From 9efa5e50598c5568b0678bb411b239a0b6e9a328 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:03:15 +0800 Subject: ACPI / video: Fix initial level validity test When testing if the firmware's initial value is valid, we should use the corrected level value instead of the raw value returned from firmware. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 38c3a28d6392..bf521b36c2f9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -856,7 +856,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) * or an index). Set the backlight to max_level in this case. */ for (i = 2; i < br->count; i++) - if (level_old == br->levels[i]) + if (level == br->levels[i]) break; if (i == br->count) level = max_level; -- cgit v1.2.3 From 2c62333a408f5badd2d2ffd7177f95deeccc5ca4 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:07:10 +0800 Subject: ACPI / video: Quirk initial backlight level 0 Some firmware doesn't initialize initial backlight level to a proper value and _BQC will return 0 on first time evaluation. We used to be able to detect such incorrect value with our code logic, as value 0 normally isn't a valid value in _BCL. But with the introduction of Win8, firmware begins to fill _BCL with values from 0 to 100, now 0 becomes a valid value but that value will make user's screen black. This patch test initial _BQC for value 0, if such a value is returned, do not use it. References: https://bugzilla.kernel.org/show_bug.cgi?id=64031 References: https://bugzilla.kernel.org/show_bug.cgi?id=61231 References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Reported-by: Qingshuai Tian Tested-by: Aaron Lu # on "Idealpad u330p" Reported-and-tested-by: # on "Acer Aspire V5-573G" Reported-and-tested-by: Kirill Tkhai # on "HP 250 G1" Signed-off-by: Aaron Lu Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bf521b36c2f9..a049fa9360d0 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -858,7 +858,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) for (i = 2; i < br->count; i++) if (level == br->levels[i]) break; - if (i == br->count) + if (i == br->count || !level) level = max_level; } -- cgit v1.2.3 From 906f187b93d4b15e54066802f2a3100ca4681296 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:18:16 +0800 Subject: Revert "ACPI / video: Ignore BIOS initial backlight value for HP 250 G1" This reverts commit e37f14a5fb85522f3bbf88ece6134c4e610ed598. It turned out other systems also share the same problem with bug 63111 so I made a patch to catch initial brightness level 0 problem. With that patch applied, we do not need to place HP 250 G1 in DMI table. References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a049fa9360d0..18dbdff4656e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -504,14 +504,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), }, }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP 250 G1", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"), - }, - }, {} }; -- cgit v1.2.3 From 9968e459f1378a1c00301472cfe672497fe001d5 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 5 Nov 2013 21:25:32 +0100 Subject: ACPI / event: remove unneeded NULL pointer check nla_data() cannot return NULL as it simply adds NLA_HDRLEN to the passed pointer. The NULL pointer check is therefore superfluous. Remove it. Found by smatch: drivers/acpi/event.c:130 acpi_bus_generate_netlink_event() warn: can 'event' even be NULL? Signed-off-by: Mathias Krause Signed-off-by: Rafael J. Wysocki --- drivers/acpi/event.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 8247fcdde079..fdef416c0ff6 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -127,11 +127,6 @@ int acpi_bus_generate_netlink_event(const char *device_class, } event = nla_data(attr); - if (!event) { - nlmsg_free(skb); - return -EINVAL; - } - memset(event, 0, sizeof(struct acpi_genl_event)); strcpy(event->device_class, device_class); -- cgit v1.2.3 From 7b98118aaa5d75644c48f41fc5d0cc181e478383 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:45:40 +0100 Subject: ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines There are two different interfaces for queuing up work items on the ACPI hotplug workqueue, alloc_acpi_hp_work() used by PCI and PCI host bridge hotplug code and acpi_os_hotplug_execute() used by the common ACPI hotplug code and docking stations. They both are somewhat cumbersome to use and work slightly differently. The users of alloc_acpi_hp_work() have to submit a work function that will extract the necessary data items from a struct acpi_hp_work object allocated by alloc_acpi_hp_work() and then will free that object, while it would be more straightforward to simply use a work function with one more argument and let the interface take care of the execution details. The users of acpi_os_hotplug_execute() also have to deal with the fact that it takes only one argument in addition to the work function pointer, although acpi_os_execute_deferred() actually takes care of the allocation and freeing of memory, so it would have been able to pass more arguments to the work function if it hadn't been constrained by the connection with acpi_os_execute(). Moreover, while alloc_acpi_hp_work() makes GFP_KERNEL memory allocations, which is correct, because hotplug work items are always queued up from process context, acpi_os_hotplug_execute() uses GFP_ATOMIC, as that is needed by acpi_os_execute(). Also, acpi_os_execute_deferred() queued up by it waits for the ACPI event workqueues to flush before executing the work function, whereas alloc_acpi_hp_work() can't do anything similar. That leads to somewhat arbitrary differences in behavior between various ACPI hotplug code paths and has to be straightened up. For this reason, replace both alloc_acpi_hp_work() and acpi_os_hotplug_execute() with a single interface, acpi_hotplug_execute(), combining their behavior and being more friendly to its users than any of the two. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/dock.c | 25 ++----------- drivers/acpi/internal.h | 2 +- drivers/acpi/osl.c | 96 ++++++++++++++++++++++++------------------------- drivers/acpi/pci_root.c | 14 ++------ drivers/acpi/scan.c | 43 +++++----------------- 5 files changed, 61 insertions(+), 119 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 05ea4be01a83..eab7d1145bfa 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -671,39 +671,20 @@ static void dock_notify(struct dock_station *ds, u32 event) } } -struct dock_data { - struct dock_station *ds; - u32 event; -}; - -static void acpi_dock_deferred_cb(void *context) +static void acpi_dock_deferred_cb(void *data, u32 event) { - struct dock_data *data = context; - acpi_scan_lock_acquire(); - dock_notify(data->ds, data->event); + dock_notify(data, event); acpi_scan_lock_release(); - kfree(data); } static void dock_notify_handler(acpi_handle handle, u32 event, void *data) { - struct dock_data *dd; - if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return; - dd = kmalloc(sizeof(*dd), GFP_KERNEL); - if (dd) { - acpi_status status; - - dd->ds = data; - dd->event = event; - status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); - if (ACPI_FAILURE(status)) - kfree(dd); - } + acpi_hotplug_execute(acpi_dock_deferred_cb, data, event); } /** diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 80cd1a10c4c3..c6db680c826c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,7 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src); +void acpi_bus_device_eject(void *data, u32 ost_src); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c7f66e..cfc3e260a688 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -61,7 +61,6 @@ struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; struct work_struct work; - int wait; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -1067,9 +1066,6 @@ static void acpi_os_execute_deferred(struct work_struct *work) { struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - if (dpc->wait) - acpi_os_wait_events_complete(); - dpc->function(dpc->context); kfree(dpc); } @@ -1089,8 +1085,8 @@ static void acpi_os_execute_deferred(struct work_struct *work) * ******************************************************************************/ -static acpi_status __acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context, int hp) +acpi_status acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; @@ -1117,20 +1113,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, dpc->context = context; /* - * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq - * because the hotplug code may call driver .remove() functions, - * which invoke flush_scheduled_work/acpi_os_wait_events_complete - * to flush these workqueues. - * * To prevent lockdep from complaining unnecessarily, make sure that * there is a different static lockdep key for each workqueue by using * INIT_WORK() for each of them separately. */ - if (hp) { - queue = kacpi_hotplug_wq; - dpc->wait = 1; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - } else if (type == OSL_NOTIFY_HANDLER) { + if (type == OSL_NOTIFY_HANDLER) { queue = kacpi_notify_wq; INIT_WORK(&dpc->work, acpi_os_execute_deferred); } else { @@ -1155,28 +1142,59 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, } return status; } +EXPORT_SYMBOL(acpi_os_execute); -acpi_status acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context) +void acpi_os_wait_events_complete(void) { - return __acpi_os_execute(type, function, context, 0); + flush_workqueue(kacpid_wq); + flush_workqueue(kacpi_notify_wq); } -EXPORT_SYMBOL(acpi_os_execute); -acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, - void *context) +struct acpi_hp_work { + struct work_struct work; + acpi_hp_callback func; + void *data; + u32 src; +}; + +static void acpi_hotplug_work_fn(struct work_struct *work) { - return __acpi_os_execute(0, function, context, 1); + struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work); + + acpi_os_wait_events_complete(); + hpw->func(hpw->data, hpw->src); + kfree(hpw); } -EXPORT_SYMBOL(acpi_os_hotplug_execute); -void acpi_os_wait_events_complete(void) +acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) { - flush_workqueue(kacpid_wq); - flush_workqueue(kacpi_notify_wq); + struct acpi_hp_work *hpw; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Scheduling function [%p(%p, %u)] for deferred execution.\n", + func, data, src)); + + hpw = kmalloc(sizeof(*hpw), GFP_KERNEL); + if (!hpw) + return AE_NO_MEMORY; + + INIT_WORK(&hpw->work, acpi_hotplug_work_fn); + hpw->func = func; + hpw->data = data; + hpw->src = src; + /* + * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because + * the hotplug code may call driver .remove() functions, which may + * invoke flush_scheduled_work()/acpi_os_wait_events_complete() to flush + * these workqueues. + */ + if (!queue_work(kacpi_hotplug_wq, &hpw->work)) { + kfree(hpw); + return AE_ERROR; + } + return AE_OK; } -EXPORT_SYMBOL(acpi_os_wait_events_complete); acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) @@ -1825,25 +1843,3 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, { __acpi_os_prepare_extended_sleep = func; } - - -void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, - void (*func)(struct work_struct *work)) -{ - struct acpi_hp_work *hp_work; - int ret; - - hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); - if (!hp_work) - return; - - hp_work->handle = handle; - hp_work->type = type; - hp_work->context = context; - - INIT_WORK(&hp_work->work, func); - ret = queue_work(kacpi_hotplug_wq, &hp_work->work); - if (!ret) - kfree(hp_work); -} -EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d77f0bf7eda0..417876bce854 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -592,17 +592,10 @@ static void handle_root_bridge_insertion(acpi_handle handle) acpi_handle_err(handle, "cannot add bridge to acpi list\n"); } -static void _handle_hotplug_event_root(struct work_struct *work) +static void hotplug_event_root(void *data, u32 type) { + acpi_handle handle = data; struct acpi_pci_root *root; - struct acpi_hp_work *hp_work; - acpi_handle handle; - u32 type; - - hp_work = container_of(work, struct acpi_hp_work, work); - handle = hp_work->handle; - type = hp_work->type; - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ acpi_scan_lock_acquire(); @@ -654,8 +647,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) static void handle_hotplug_event_root(acpi_handle handle, u32 type, void *context) { - alloc_acpi_hp_work(handle, type, context, - _handle_hotplug_event_root); + acpi_hotplug_execute(hotplug_event_root, handle, type); } static acpi_status __init diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5cd7f8c5666a..276cde70a514 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,8 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) +void acpi_bus_device_eject(void *data, u32 ost_src) { + struct acpi_device *device = data; acpi_handle handle = device->handle; struct acpi_scan_handler *handler; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; @@ -327,8 +328,9 @@ void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) goto out; } -static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) +static void acpi_scan_bus_device_check(void *data, u32 ost_source) { + acpi_handle handle = data; struct acpi_device *device = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; @@ -363,18 +365,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) unlock_device_hotplug(); } -static void acpi_scan_bus_check(void *context) -{ - acpi_scan_bus_device_check((acpi_handle)context, - ACPI_NOTIFY_BUS_CHECK); -} - -static void acpi_scan_device_check(void *context) -{ - acpi_scan_bus_device_check((acpi_handle)context, - ACPI_NOTIFY_DEVICE_CHECK); -} - static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) { u32 ost_status; @@ -403,18 +393,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); } -/** - * acpi_bus_hot_remove_device: Hot-remove a device and its children. - * @context: Address of the ACPI device object to hot-remove. - */ -static void acpi_bus_hot_remove_device(void *context) -{ - acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); -} - static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { - acpi_osd_exec_callback callback; struct acpi_scan_handler *handler = data; struct acpi_device *adev; acpi_status status; @@ -425,11 +405,9 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); - callback = acpi_scan_bus_check; break; case ACPI_NOTIFY_DEVICE_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); - callback = acpi_scan_device_check; break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); @@ -438,8 +416,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) goto err_out; get_device(&adev->dev); - callback = acpi_bus_hot_remove_device; - status = acpi_os_hotplug_execute(callback, adev); + status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); if (ACPI_SUCCESS(status)) return; @@ -449,7 +426,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) /* non-hotplug event; possibly handled by other handler */ return; } - status = acpi_os_hotplug_execute(callback, handle); + status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); if (ACPI_SUCCESS(status)) return; @@ -484,11 +461,6 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); -static void acpi_eject_store_work(void *context) -{ - acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT); -} - static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -511,7 +483,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); get_device(&acpi_device->dev); - status = acpi_os_hotplug_execute(acpi_eject_store_work, acpi_device); + status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, + ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) return count; -- cgit v1.2.3 From 9ebddac7ea2a1f4b4ce3335a78312a58dfaadb4d Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Fri, 8 Nov 2013 14:03:33 -0800 Subject: ACPI, x86: Fix extended error log driver to depend on CONFIG_X86_LOCAL_APIC Randconfig build by Fengguang's robot army reported: drivers/built-in.o: In function `extlog_print': >> acpi_extlog.c:(.text+0xcc719): undefined reference to `boot_cpu_physical_apicid' The config had CONFIG_SMP=n so we picked up this definition from: : #define cpu_physical_id(cpu) boot_cpu_physical_apicid But boot_cpu_physical_apicid is defined in arch/x86/kernel/apic/apic.c which is only built if CONFIG_X86_LOCAL_APIC=y. Reported-by: Fengguang Wu Signed-off-by: Tony Luck Cc: Chen Gong Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/6be3afdcad7968f7fb7c0b681e547b3e872e44dd.1383947368.git.tony.luck@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 08eadb4a57cb..e11faae81ed9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -374,7 +374,7 @@ source "drivers/acpi/apei/Kconfig" config ACPI_EXTLOG tristate "Extended Error Log support" - depends on X86_MCE + depends on X86_MCE && X86_LOCAL_APIC select EFI select UEFI_CPER default n -- cgit v1.2.3 From 4c47cb197e136912f4eecc68ab9410487f2df831 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 9 Nov 2013 00:13:16 -0500 Subject: ACPI: delete CONFIG_ACPI_BLACKLIST_YEAR About 10 years ago, this option was created to help distros enable ACPI and not get distracted by ACPI BIOS issues in machines which were deemed old at that time, eg 1999 and earlier. After a couple of years, the high volume distros stopped bothering to set this option, and instead simply ran in ACPI mode on all systems with an ACPI BIOS -- regardless of BIOS DMI year. Recently there have been some ACPI-enabled systems with no DMI, mandating that CONFIG_ACPI_BLACKLIST_YEAR=0. So it seems vanishingly unlikely that this option is helping anybody run a 2013 kernel on a 1998 system, and now more systems mandate this option be disabled, so we simplify by deleting it entirely. Signed-off-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 11 ----------- drivers/acpi/blacklist.c | 35 ----------------------------------- 2 files changed, 46 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 6efe2ac6902f..7e5c18a60541 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -251,17 +251,6 @@ config ACPI_INITRD_TABLE_OVERRIDE initrd, therefore it's safe to say Y. See Documentation/acpi/initrd_table_override.txt for details -config ACPI_BLACKLIST_YEAR - int "Disable ACPI for systems before Jan 1st this year" if X86_32 - default 0 - help - Enter a 4-digit year, e.g., 2001, to disable ACPI by default - on platforms with DMI BIOS date before January 1st that year. - "acpi=force" can be used to override this mechanism. - - Enter 0 to disable this mechanism and allow ACPI to - run by default no matter what the year. (default) - config ACPI_DEBUG bool "Debug Statements" default n diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9515f18898b2..a87958830849 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -75,39 +75,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { {""} }; -#if CONFIG_ACPI_BLACKLIST_YEAR - -static int __init blacklist_by_year(void) -{ - int year; - - /* Doesn't exist? Likely an old system */ - if (!dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL)) { - printk(KERN_ERR PREFIX "no DMI BIOS year, " - "acpi=force is required to enable ACPI\n" ); - return 1; - } - /* 0? Likely a buggy new BIOS */ - if (year == 0) { - printk(KERN_ERR PREFIX "DMI BIOS year==0, " - "assuming ACPI-capable machine\n" ); - return 0; - } - if (year < CONFIG_ACPI_BLACKLIST_YEAR) { - printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " - "acpi=force is required to enable ACPI\n", - year, CONFIG_ACPI_BLACKLIST_YEAR); - return 1; - } - return 0; -} -#else -static inline int blacklist_by_year(void) -{ - return 0; -} -#endif - int __init acpi_blacklisted(void) { int i = 0; @@ -166,8 +133,6 @@ int __init acpi_blacklisted(void) } } - blacklisted += blacklist_by_year(); - dmi_check_system(acpi_osi_dmi_table); return blacklisted; -- cgit v1.2.3 From a4d97536a1a20a70a65ded5d445013a3904d5a8d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 12 Nov 2013 11:48:19 +0200 Subject: ACPI / LPSS: add ACPI IDs for newer Intel PCHs Some recent Intel PCHs with LPSS have different ACPI IDs for the LPSS devices, so add these to the list as well. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index fb78bb9ad8f6..242885715331 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -157,6 +157,15 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "80860F41", (unsigned long)&byt_i2c_dev_desc }, { "INT33B2", }, + { "INT3430", (unsigned long)&lpt_dev_desc }, + { "INT3431", (unsigned long)&lpt_dev_desc }, + { "INT3432", (unsigned long)&lpt_dev_desc }, + { "INT3433", (unsigned long)&lpt_dev_desc }, + { "INT3434", (unsigned long)&lpt_uart_dev_desc }, + { "INT3435", (unsigned long)&lpt_uart_dev_desc }, + { "INT3436", (unsigned long)&lpt_sdio_dev_desc }, + { "INT3437", }, + { } }; -- cgit v1.2.3 From 7b1998116bbb2f3e5dd6cb9a8ee6db479b0b50a9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 11 Nov 2013 22:41:56 +0100 Subject: ACPI / driver core: Store an ACPI device pointer in struct acpi_dev_node Modify struct acpi_dev_node to contain a pointer to struct acpi_device associated with the given device object (that is, its ACPI companion device) instead of an ACPI handle corresponding to it. Introduce two new macros for manipulating that pointer in a CONFIG_ACPI-safe way, ACPI_COMPANION() and ACPI_COMPANION_SET(), and rework the ACPI_HANDLE() macro to take the above changes into account. Drop the ACPI_HANDLE_SET() macro entirely and rework its users to use ACPI_COMPANION_SET() instead. For some of them who used to pass the result of acpi_get_child() directly to ACPI_HANDLE_SET() introduce a helper routine acpi_preset_companion() doing an equivalent thing. The main motivation for doing this is that there are things represented by struct acpi_device objects that don't have valid ACPI handles (so called fixed ACPI hardware features, such as power and sleep buttons) and we would like to create platform device objects for them and "glue" them to their ACPI companions in the usual way (which currently is impossible due to the lack of valid ACPI handles). However, there are more reasons why it may be useful. First, struct acpi_device pointers allow of much better type checking than void pointers which are ACPI handles, so it should be more difficult to write buggy code using modified struct acpi_dev_node and the new macros. Second, the change should help to reduce (over time) the number of places in which the result of ACPI_HANDLE() is passed to acpi_bus_get_device() in order to obtain a pointer to the struct acpi_device associated with the given "physical" device, because now that pointer is returned by ACPI_COMPANION() directly. Finally, the change should make it easier to write generic code that will build both for CONFIG_ACPI set and unset without adding explicit compiler directives to it. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Tested-by: Mika Westerberg # on Haswell Reviewed-by: Mika Westerberg Reviewed-by: Aaron Lu # for ATA and SDIO part --- drivers/acpi/acpi_platform.c | 2 +- drivers/acpi/device_pm.c | 6 +----- drivers/acpi/glue.c | 47 ++++++++++++++++++++++---------------------- 3 files changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 8a4cfc7e71f0..dbfe49e5fd63 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -111,7 +111,7 @@ int acpi_create_platform_device(struct acpi_device *adev, pdevinfo.id = -1; pdevinfo.res = resources; pdevinfo.num_res = count; - pdevinfo.acpi_node.handle = adev->handle; + pdevinfo.acpi_node.companion = adev; pdev = platform_device_register_full(&pdevinfo); if (IS_ERR(pdev)) { dev_err(&adev->dev, "platform device creation failed: %ld\n", diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index d42b2fb5a7e9..119afda0968c 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,16 +22,12 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include +#include #include #include #include #include -#include -#include -#include - #include "internal.h" #define _COMPONENT ACPI_POWER_COMPONENT diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 10f0f40587bb..782071fd3df3 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -197,30 +197,27 @@ static void acpi_physnode_link_name(char *buf, unsigned int node_id) int acpi_bind_one(struct device *dev, acpi_handle handle) { - struct acpi_device *acpi_dev; - acpi_status status; + struct acpi_device *acpi_dev = NULL; struct acpi_device_physical_node *physical_node, *pn; char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; struct list_head *physnode_list; unsigned int node_id; int retval = -EINVAL; - if (ACPI_HANDLE(dev)) { + if (ACPI_COMPANION(dev)) { if (handle) { - dev_warn(dev, "ACPI handle is already set\n"); + dev_warn(dev, "ACPI companion already set\n"); return -EINVAL; } else { - handle = ACPI_HANDLE(dev); + acpi_dev = ACPI_COMPANION(dev); } + } else { + acpi_bus_get_device(handle, &acpi_dev); } - if (!handle) + if (!acpi_dev) return -EINVAL; get_device(dev); - status = acpi_bus_get_device(handle, &acpi_dev); - if (ACPI_FAILURE(status)) - goto err; - physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL); if (!physical_node) { retval = -ENOMEM; @@ -242,7 +239,7 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) dev_warn(dev, "Already associated with ACPI node\n"); kfree(physical_node); - if (ACPI_HANDLE(dev) != handle) + if (ACPI_COMPANION(dev) != acpi_dev) goto err; put_device(dev); @@ -259,8 +256,8 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) list_add(&physical_node->node, physnode_list); acpi_dev->physical_node_count++; - if (!ACPI_HANDLE(dev)) - ACPI_HANDLE_SET(dev, acpi_dev->handle); + if (!ACPI_COMPANION(dev)) + ACPI_COMPANION_SET(dev, acpi_dev); acpi_physnode_link_name(physical_node_name, node_id); retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, @@ -283,7 +280,7 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) return 0; err: - ACPI_HANDLE_SET(dev, NULL); + ACPI_COMPANION_SET(dev, NULL); put_device(dev); return retval; } @@ -291,19 +288,12 @@ EXPORT_SYMBOL_GPL(acpi_bind_one); int acpi_unbind_one(struct device *dev) { + struct acpi_device *acpi_dev = ACPI_COMPANION(dev); struct acpi_device_physical_node *entry; - struct acpi_device *acpi_dev; - acpi_status status; - if (!ACPI_HANDLE(dev)) + if (!acpi_dev) return 0; - status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev); - if (ACPI_FAILURE(status)) { - dev_err(dev, "Oops, ACPI handle corrupt in %s()\n", __func__); - return -EINVAL; - } - mutex_lock(&acpi_dev->physical_node_lock); list_for_each_entry(entry, &acpi_dev->physical_node_list, node) @@ -316,7 +306,7 @@ int acpi_unbind_one(struct device *dev) acpi_physnode_link_name(physnode_name, entry->node_id); sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name); sysfs_remove_link(&dev->kobj, "firmware_node"); - ACPI_HANDLE_SET(dev, NULL); + ACPI_COMPANION_SET(dev, NULL); /* acpi_bind_one() increase refcnt by one. */ put_device(dev); kfree(entry); @@ -328,6 +318,15 @@ int acpi_unbind_one(struct device *dev) } EXPORT_SYMBOL_GPL(acpi_unbind_one); +void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr) +{ + struct acpi_device *adev; + + if (!acpi_bus_get_device(acpi_get_child(parent, addr), &adev)) + ACPI_COMPANION_SET(dev, adev); +} +EXPORT_SYMBOL_GPL(acpi_preset_companion); + static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type = acpi_get_bus_type(dev); -- cgit v1.2.3 From 3a83f992490f8235661b768e53bd5f14915420ac Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Nov 2013 23:17:21 +0100 Subject: ACPI: Eliminate the DEVICE_ACPI_HANDLE() macro Since DEVICE_ACPI_HANDLE() is now literally identical to ACPI_HANDLE(), replace it with the latter everywhere and drop its definition from include/acpi.h. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- drivers/acpi/device_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 119afda0968c..b3480cf7db1a 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -544,7 +544,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, */ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) { - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *adev; int ret, d_min, d_max; @@ -652,7 +652,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) if (!device_run_wake(phys_dev)) return -EINVAL; - handle = DEVICE_ACPI_HANDLE(phys_dev); + handle = ACPI_HANDLE(phys_dev); if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(phys_dev, "ACPI handle without context in %s!\n", __func__); @@ -696,7 +696,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) if (!device_can_wakeup(dev)) return -EINVAL; - handle = DEVICE_ACPI_HANDLE(dev); + handle = ACPI_HANDLE(dev); if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; @@ -718,7 +718,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) */ struct acpi_device *acpi_dev_pm_get_node(struct device *dev) { - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *adev; return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL; -- cgit v1.2.3 From a104b4d467d1c4a09727bac2816928aef3304d3a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Nov 2013 23:18:32 +0100 Subject: ACPI / bind: Use (put|get)_device() on ACPI device objects too When associating a "physical" device with an ACPI device object acpi_bind_one() only uses get_device() to increment the reference counter of the former, but there is no reason not to do that with the latter too. Among other things, that may help to avoid use-after-free when an ACPI device object is freed without calling acpi_unbind_one() for all "physical" devices associated with it (that only can happen in buggy code, but then it's better if the kernel doesn't crash as a result of a bug). For this reason, modify acpi_bind_one() to apply get_device() to the ACPI device object too and update acpi_unbind_one() to drop that reference using put_device() as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: Lan Tianyu --- drivers/acpi/glue.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 782071fd3df3..a22a295edb69 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -217,6 +217,7 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) if (!acpi_dev) return -EINVAL; + get_device(&acpi_dev->dev); get_device(dev); physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL); if (!physical_node) { @@ -243,6 +244,7 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) goto err; put_device(dev); + put_device(&acpi_dev->dev); return 0; } if (pn->node_id == node_id) { @@ -282,6 +284,7 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) err: ACPI_COMPANION_SET(dev, NULL); put_device(dev); + put_device(&acpi_dev->dev); return retval; } EXPORT_SYMBOL_GPL(acpi_bind_one); @@ -307,8 +310,9 @@ int acpi_unbind_one(struct device *dev) sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name); sysfs_remove_link(&dev->kobj, "firmware_node"); ACPI_COMPANION_SET(dev, NULL); - /* acpi_bind_one() increase refcnt by one. */ + /* Drop references taken by acpi_bind_one(). */ put_device(dev); + put_device(&acpi_dev->dev); kfree(entry); break; } -- cgit v1.2.3 From 86b0cc12bba9cb9cc3c20974dec565f44c961fc3 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 13 Nov 2013 11:27:42 +0800 Subject: ACPI / AC: Remove struct acpi_device pointer from struct acpi_ac Now the pointer of struct acpi_device can be got by ACPI_COMPANION(struct acpi_ac->pdev->dev). So the pointer is not necessary and remove it. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index b9f0d5f4bba5..8711e3797165 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -56,7 +56,6 @@ static int ac_sleep_before_get_state_ms; struct acpi_ac { struct power_supply charger; - struct acpi_device *adev; struct platform_device *pdev; unsigned long long state; }; @@ -70,8 +69,9 @@ struct acpi_ac { static int acpi_ac_get_state(struct acpi_ac *ac) { acpi_status status; + acpi_handle handle = ACPI_HANDLE(&ac->pdev->dev); - status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL, + status = acpi_evaluate_integer(handle, "_PSR", NULL, &ac->state); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, @@ -119,6 +119,7 @@ static enum power_supply_property ac_props[] = { static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) { struct acpi_ac *ac = data; + struct acpi_device *adev; if (!ac) return; @@ -141,10 +142,11 @@ static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - acpi_bus_generate_netlink_event(ac->adev->pnp.device_class, + adev = ACPI_COMPANION(&ac->pdev->dev); + acpi_bus_generate_netlink_event(adev->pnp.device_class, dev_name(&ac->pdev->dev), event, (u32) ac->state); - acpi_notifier_call_chain(ac->adev, event, (u32) ac->state); + acpi_notifier_call_chain(adev, event, (u32) ac->state); kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); } @@ -178,8 +180,8 @@ static int acpi_ac_probe(struct platform_device *pdev) if (!pdev) return -EINVAL; - result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); - if (result) + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) return -ENODEV; ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); @@ -188,7 +190,6 @@ static int acpi_ac_probe(struct platform_device *pdev) strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); strcpy(acpi_device_class(adev), ACPI_AC_CLASS); - ac->adev = adev; ac->pdev = pdev; platform_set_drvdata(pdev, ac); -- cgit v1.2.3 From 36b15875a7819a2ec4cb5748ff7096ad7bd86cbb Mon Sep 17 00:00:00 2001 From: Puneet Kumar Date: Fri, 15 Nov 2013 11:41:29 -0800 Subject: ACPI / EC: Ensure lock is acquired before accessing ec struct members A bug was introduced by commit b76b51ba0cef ('ACPI / EC: Add more debug info and trivial code cleanup') that erroneously caused the struct member to be accessed before acquiring the required lock. This change fixes it by ensuring the lock acquisition is done first. Found by Aaron Durbin Fixes: b76b51ba0cef ('ACPI / EC: Add more debug info and trivial code cleanup') References: http://crbug.com/319019 Signed-off-by: Puneet Kumar Reviewed-by: Aaron Durbin [olof: Commit message reworded a bit] Signed-off-by: Olof Johansson Cc: 3.8+ # 3.8+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a06d98374705..15986f32009e 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -175,9 +175,10 @@ static void start_transaction(struct acpi_ec *ec) static void advance_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; - struct transaction *t = ec->curr; + struct transaction *t; spin_lock_irqsave(&ec->lock, flags); + t = ec->curr; if (!t) goto unlock; if (t->wlen > t->wi) { -- cgit v1.2.3 From 545ef368e08fda654b6e63ce522c66339aa29156 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 15 Nov 2013 14:39:12 +0800 Subject: ACPI / video: clean up DMI table for initial black screen problem With commit 2c62333a408f "ACPI / video: Quirk initial backlight level 0" we do not need to have the following systems in DMI table, so remove them. HP Pavilion m4, HP 1000 Notebook PC, HP Pavilion g6 Notebook PC, HP Pavilion dm4, Fujitsu E753, HP Folio 13-2000. With this change, the use_bios_initial_backlight module parameter is no longer needed and thus removed. Signed-off-by: Aaron Lu Tested-by: Alex Hung # for HP 1000 Notebook PC Tested-by: Gustavo Maciel Dias Vieira # for HP Pavilion dm4 Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 87 ++++++++-------------------------------------------- 1 file changed, 12 insertions(+), 75 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 18dbdff4656e..995e91bcb97b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -81,13 +81,6 @@ module_param(brightness_switch_enabled, bool, 0644); static bool allow_duplicates; module_param(allow_duplicates, bool, 0644); -/* - * Some BIOSes claim they use minimum backlight at boot, - * and this may bring dimming screen after boot - */ -static bool use_bios_initial_backlight = 1; -module_param(use_bios_initial_backlight, bool, 0644); - /* * For Windows 8 systems: if set ture and the GPU driver has * registered a backlight interface, skip registering ACPI video's. @@ -406,12 +399,6 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } -static int video_ignore_initial_backlight(const struct dmi_system_id *d) -{ - use_bios_initial_backlight = 0; - return 0; -} - static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -456,54 +443,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP Folio 13-2000", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), - }, - }, - { - .callback = video_ignore_initial_backlight, - .ident = "Fujitsu E753", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "FUJITSU"), - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E753"), - }, - }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP Pavilion dm4", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"), - }, - }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP Pavilion g6 Notebook PC", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"), - }, - }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP 1000 Notebook PC", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP 1000 Notebook PC"), - }, - }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP Pavilion m4", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), - }, - }, {} }; @@ -839,20 +778,18 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (!device->cap._BQC) goto set_level; - if (use_bios_initial_backlight) { - level = acpi_video_bqc_value_to_level(device, level_old); - /* - * On some buggy laptops, _BQC returns an uninitialized - * value when invoked for the first time, i.e. - * level_old is invalid (no matter whether it's a level - * or an index). Set the backlight to max_level in this case. - */ - for (i = 2; i < br->count; i++) - if (level == br->levels[i]) - break; - if (i == br->count || !level) - level = max_level; - } + level = acpi_video_bqc_value_to_level(device, level_old); + /* + * On some buggy laptops, _BQC returns an uninitialized + * value when invoked for the first time, i.e. + * level_old is invalid (no matter whether it's a level + * or an index). Set the backlight to max_level in this case. + */ + for (i = 2; i < br->count; i++) + if (level == br->levels[i]) + break; + if (i == br->count || !level) + level = max_level; set_level: result = acpi_video_device_lcd_set_level(device, level); -- cgit v1.2.3 From 5beaee4f195d0297473da9a45459050b561e10cf Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Nov 2013 00:54:00 +0100 Subject: ACPI / hotplug: Fix acpi_bus_get_device() return value check Since acpi_bus_get_device() returns a plain int and not acpi_status, ACPI_FAILURE() should not be used for checking its return value. Fix that. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 276cde70a514..4698060ba3f0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -411,8 +411,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); - status = acpi_bus_get_device(handle, &adev); - if (ACPI_FAILURE(status)) + if (acpi_bus_get_device(handle, &adev)) goto err_out; get_device(&adev->dev); -- cgit v1.2.3 From c1beb0bdb5b3ef670af3ab946434f7fc55d4c7a3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Nov 2013 00:54:08 +0100 Subject: ACPI / hotplug: Fix PCI host bridge hot removal Since the PCI host bridge scan handler does not set hotplug.enabled, the check of it in acpi_bus_device_eject() effectively prevents the root bridge hot removal from working after commit a3b1b1ef78cd (ACPI / hotplug: Merge device hot-removal routines). However, that check is not necessary, because the other acpi_bus_device_eject() users, acpi_hotplug_notify_cb and acpi_eject_store(), do the same check by themselves before executing that function. For this reason, remove the scan handler check from acpi_bus_device_eject() to make PCI hot bridge hot removal work again. Fixes: a3b1b1ef78cd (ACPI / hotplug: Merge device hot-removal routines) Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4698060ba3f0..821d154221d5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -289,24 +289,17 @@ void acpi_bus_device_eject(void *data, u32 ost_src) { struct acpi_device *device = data; acpi_handle handle = device->handle; - struct acpi_scan_handler *handler; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; lock_device_hotplug(); mutex_lock(&acpi_scan_lock); - handler = device->handler; - if (!handler || !handler->hotplug.enabled) { - put_device(&device->dev); - goto err_support; - } - if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - if (handler->hotplug.mode == AHM_CONTAINER) + if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); error = acpi_scan_hot_remove(device); -- cgit v1.2.3 From f516bde5122422889398d10e8e746d18860bd42e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Nov 2013 00:54:17 +0100 Subject: ACPI / PCI root: Clear driver_data before failing enumeration If a PCI host bridge cannot be enumerated due to an error in pci_acpi_scan_root(), its ACPI device object's driver_data field has to be cleared by acpi_pci_root_add() before freeing the object pointed to by that field, or some later acpi_pci_find_root() checks that should fail may succeed and cause quite a bit of confusion to ensue. Fix acpi_pci_root_add() to clear device->driver_data before returning an error code as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/pci_root.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 417876bce854..b5cb729328a4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -525,6 +525,7 @@ static int acpi_pci_root_add(struct acpi_device *device, dev_err(&device->dev, "Bus %04x:%02x not present in PCI namespace\n", root->segment, (unsigned int)root->secondary.start); + device->driver_data = NULL; result = -ENODEV; goto end; } -- cgit v1.2.3 From 883461679ad1ed6e09135adf8c02bb98d7962623 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 18 Nov 2013 14:18:47 +0100 Subject: ACPI / scan: Set flags.match_driver in acpi_bus_scan_fixed() Before commit 6931007cc90b (ACPI / scan: Start matching drivers after trying scan handlers) the match_driver flag for all devices was set in acpi_add_single_object(), but now it is set by acpi_bus_device_attach() which is not called for the "fixed" devices added by acpi_bus_scan_fixed(). This means that flags.match_driver is never set for those devices now, so make acpi_bus_scan_fixed() set it before calling device_attach(). Fixes: 6931007cc90b (ACPI / scan: Start matching drivers after trying scan handlers) Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 821d154221d5..ce518867a18a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1990,6 +1990,7 @@ static int acpi_bus_scan_fixed(void) if (result) return result; + device->flags.match_driver = true; result = device_attach(&device->dev); if (result < 0) return result; @@ -2006,6 +2007,7 @@ static int acpi_bus_scan_fixed(void) if (result) return result; + device->flags.match_driver = true; result = device_attach(&device->dev); } -- cgit v1.2.3 From 68eb55031da7c967d954e5f9415cd05f4abdb692 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 15:19:38 +0100 Subject: genetlink: pass family to functions using groups This doesn't really change anything, but prepares for the next patch that will change the APIs to pass the group ID within the family, rather than the global group ID. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/acpi/event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 8247fcdde079..68a8755202ec 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -146,7 +146,8 @@ int acpi_bus_generate_netlink_event(const char *device_class, return result; } - genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); + genlmsg_multicast(&acpi_event_genl_family, + skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); return 0; } -- cgit v1.2.3 From 2a94fe48f32ccf7321450a2cc07f2b724a444e5b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 15:19:39 +0100 Subject: genetlink: make multicast groups const, prevent abuse Register generic netlink multicast groups as an array with the family and give them contiguous group IDs. Then instead of passing the global group ID to the various functions that send messages, pass the ID relative to the family - for most families that's just 0 because the only have one group. This avoids the list_head and ID in each group, adding a new field for the mcast group ID offset to the family. At the same time, this allows us to prevent abusing groups again like the quota and dropmon code did, since we can now check that a family only uses a group it owns. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/acpi/event.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 68a8755202ec..aeb5aa6ce068 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -78,15 +78,17 @@ enum { #define ACPI_GENL_VERSION 0x01 #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" +static const struct genl_multicast_group acpi_event_mcgrps[] = { + { .name = ACPI_GENL_MCAST_GROUP_NAME, }, +}; + static struct genl_family acpi_event_genl_family = { .id = GENL_ID_GENERATE, .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, .maxattr = ACPI_GENL_ATTR_MAX, -}; - -static struct genl_multicast_group acpi_event_mcgrp = { - .name = ACPI_GENL_MCAST_GROUP_NAME, + .mcgrps = acpi_event_mcgrps, + .n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps), }; int acpi_bus_generate_netlink_event(const char *device_class, @@ -146,8 +148,7 @@ int acpi_bus_generate_netlink_event(const char *device_class, return result; } - genlmsg_multicast(&acpi_event_genl_family, - skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); + genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC); return 0; } @@ -155,18 +156,7 @@ EXPORT_SYMBOL(acpi_bus_generate_netlink_event); static int acpi_event_genetlink_init(void) { - int result; - - result = genl_register_family(&acpi_event_genl_family); - if (result) - return result; - - result = genl_register_mc_group(&acpi_event_genl_family, - &acpi_event_mcgrp); - if (result) - genl_unregister_family(&acpi_event_genl_family); - - return result; + return genl_register_family(&acpi_event_genl_family); } #else -- cgit v1.2.3 From ca499fc87ed945094d952da0eb7eea7dbeb1feec Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 20 Nov 2013 14:25:34 +0100 Subject: ACPI / hotplug: Fix conflicted PCI bridge notify handlers The PCI host bridge scan handler installs its own notify handler, handle_hotplug_event_root(), by itself. Nevertheless, the ACPI hotplug framework also installs the common notify handler, acpi_hotplug_notify_cb(), for PCI root bridges. This causes acpi_hotplug_notify_cb() to call _OST method with unsupported error as hotplug.enabled is not set. To address this issue, introduce hotplug.ignore flag, which indicates that the scan handler installs its own notify handler by itself. The ACPI hotplug framework does not install the common notify handler when this flag is set. Signed-off-by: Toshi Kani [rjw: Changed the name of the new flag] Cc: 3.9+ # 3.9+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 3 +++ drivers/acpi/scan.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b5cb729328a4..a84ea1b51a89 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -65,6 +65,9 @@ static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, .attach = acpi_pci_root_add, .detach = acpi_pci_root_remove, + .hotplug = { + .ignore = true, + }, }; static DEFINE_MUTEX(osc_lock); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ce518867a18a..e76b5230f476 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1773,7 +1773,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) */ list_for_each_entry(hwid, &pnp.ids, list) { handler = acpi_scan_match_handler(hwid->id, NULL); - if (handler) { + if (handler && !handler->hotplug.ignore) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_hotplug_notify_cb, handler); break; -- cgit v1.2.3 From 51468a9d3a80249a218a854100c6d5d0eb8b781e Mon Sep 17 00:00:00 2001 From: Al Stone Date: Wed, 20 Nov 2013 15:45:51 -0700 Subject: ACPI / sleep: clean up compiler warning about uninitialized field Initialize pwr_btn_status as disabled which (a) makes sure it is in a proper state to start, and (b) cleans up a compiler warning about an uninitialized variable. Signed-off-by: Al Stone Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 14df30580e15..721e949e606e 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -525,7 +525,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) * generate wakeup events. */ if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) { - acpi_event_status pwr_btn_status; + acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED; acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); -- cgit v1.2.3 From bf9b448ef8430548d0608a38ebddbf7f6ca14ed1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 21 Nov 2013 12:17:20 +0800 Subject: ACPICA: Debug output: Do not emit function nesting level for kernel build. The nesting level is really only useful during a single-thread execution. Therefore, only enable this output for the AcpiExec utility. Also, only emit the thread ID when executing under AcpiExec. (Context switches are still detected and a message is emitted.) ACPICA BZ 972. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utdebug.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 1a67b3944b3b..03ae8affe48f 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -185,6 +185,7 @@ acpi_debug_print(u32 requested_debug_level, } acpi_gbl_prev_thread_id = thread_id; + acpi_gbl_nesting_level = 0; } /* @@ -193,13 +194,21 @@ acpi_debug_print(u32 requested_debug_level, */ acpi_os_printf("%9s-%04ld ", module_name, line_number); +#ifdef ACPI_EXEC_APP + /* + * For acpi_exec only, emit the thread ID and nesting level. + * Note: nesting level is really only useful during a single-thread + * execution. Otherwise, multiple threads will keep resetting the + * level. + */ if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf("[%u] ", (u32)thread_id); } - acpi_os_printf("[%02ld] %-22.22s: ", - acpi_gbl_nesting_level, - acpi_ut_trim_function_name(function_name)); + acpi_os_printf("[%02ld] ", acpi_gbl_nesting_level); +#endif + + acpi_os_printf("%-22.22s: ", acpi_ut_trim_function_name(function_name)); va_start(args, format); acpi_os_vprintf(format, args); @@ -420,7 +429,9 @@ acpi_ut_exit(u32 line_number, component_id, "%s\n", acpi_gbl_fn_exit_str); } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_exit) @@ -467,7 +478,9 @@ acpi_ut_status_exit(u32 line_number, } } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) @@ -504,7 +517,9 @@ acpi_ut_value_exit(u32 line_number, ACPI_FORMAT_UINT64(value)); } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) @@ -540,7 +555,9 @@ acpi_ut_ptr_exit(u32 line_number, ptr); } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } #endif -- cgit v1.2.3 From 9a0a35972591f91167556b4a61673d08ef07f310 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 21 Nov 2013 12:17:34 +0800 Subject: ACPICA: Resources: Fix loop termination for the get AML length function. The loop terminates on a NULL resource pointer, which can never happen since the loop simply increments a valid resource pointer. This fix changes the loop to terminate on an end-of-buffer condition. Problem can be seen by callers to AcpiSetCurrentResources with an invalid or corrupted resource descriptor; or a resource descriptor without an END_TAG descriptor. (refined by Bob Moore) Reported-by: Dan Carpenter Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acresrc.h | 6 +++--- drivers/acpi/acpica/rscalc.c | 9 +++++++-- drivers/acpi/acpica/rscreate.c | 36 +++++++++++++++++------------------- drivers/acpi/acpica/rsutils.c | 2 +- 4 files changed, 28 insertions(+), 25 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index f691d0e4d9fa..ff97430455cb 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -184,7 +184,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, struct acpi_buffer *output_buffer); acpi_status -acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, +acpi_rs_create_aml_resources(struct acpi_buffer *resource_list, struct acpi_buffer *output_buffer); acpi_status @@ -227,8 +227,8 @@ acpi_rs_get_list_length(u8 * aml_buffer, u32 aml_buffer_length, acpi_size * size_needed); acpi_status -acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer, - acpi_size * size_needed); +acpi_rs_get_aml_length(struct acpi_resource *resource_list, + acpi_size resource_list_size, acpi_size * size_needed); acpi_status acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index b62a0f4f4f9b..b60c9cf82862 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -174,6 +174,7 @@ acpi_rs_stream_option_length(u32 resource_length, * FUNCTION: acpi_rs_get_aml_length * * PARAMETERS: resource - Pointer to the resource linked list + * resource_list_size - Size of the resource linked list * size_needed - Where the required size is returned * * RETURN: Status @@ -185,16 +186,20 @@ acpi_rs_stream_option_length(u32 resource_length, ******************************************************************************/ acpi_status -acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) +acpi_rs_get_aml_length(struct acpi_resource *resource, + acpi_size resource_list_size, acpi_size * size_needed) { acpi_size aml_size_needed = 0; + struct acpi_resource *resource_end; acpi_rs_length total_size; ACPI_FUNCTION_TRACE(rs_get_aml_length); /* Traverse entire list of internal resource descriptors */ - while (resource) { + resource_end = + ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size); + while (resource < resource_end) { /* Validate the descriptor type */ diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 65f3e1c5b598..3a2ace93e62c 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -418,22 +418,21 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * * FUNCTION: acpi_rs_create_aml_resources * - * PARAMETERS: linked_list_buffer - Pointer to the resource linked list - * output_buffer - Pointer to the user's buffer + * PARAMETERS: resource_list - Pointer to the resource list buffer + * output_buffer - Where the AML buffer is returned * * RETURN: Status AE_OK if okay, else a valid acpi_status code. * If the output_buffer is too small, the error will be * AE_BUFFER_OVERFLOW and output_buffer->Length will point * to the size buffer needed. * - * DESCRIPTION: Takes the linked list of device resources and - * creates a bytestream to be used as input for the - * _SRS control method. + * DESCRIPTION: Converts a list of device resources to an AML bytestream + * to be used as input for the _SRS control method. * ******************************************************************************/ acpi_status -acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, +acpi_rs_create_aml_resources(struct acpi_buffer *resource_list, struct acpi_buffer *output_buffer) { acpi_status status; @@ -441,16 +440,16 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, ACPI_FUNCTION_TRACE(rs_create_aml_resources); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", - linked_list_buffer)); + /* Params already validated, no need to re-validate here */ - /* - * Params already validated, so we don't re-validate here - * - * Pass the linked_list_buffer into a module that calculates - * the buffer size needed for the byte stream. - */ - status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ResourceList Buffer = %p\n", + resource_list->pointer)); + + /* Get the buffer size needed for the AML byte stream */ + + status = acpi_rs_get_aml_length(resource_list->pointer, + resource_list->length, + &aml_size_needed); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", (u32)aml_size_needed, acpi_format_exception(status))); @@ -467,10 +466,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, /* Do the conversion */ - status = - acpi_rs_convert_resources_to_aml(linked_list_buffer, - aml_size_needed, - output_buffer->pointer); + status = acpi_rs_convert_resources_to_aml(resource_list->pointer, + aml_size_needed, + output_buffer->pointer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index aef303d56d86..14a7982c9961 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -753,7 +753,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, * Convert the linked list into a byte stream */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); + status = acpi_rs_create_aml_resources(in_buffer, &buffer); if (ACPI_FAILURE(status)) { goto cleanup; } -- cgit v1.2.3 From 794ba09bf30054c81832e61b49a64a56c95c5a9f Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Thu, 21 Nov 2013 12:19:55 +0800 Subject: ACPICA: Delete all attached data objects during namespace node deletion. This fix updates namespace node deletion to delete the entire list of attached objects (attached via acpi_attach_data) instead of just one of the attached items. ACPICA BZ 1024. Tomasz Nowicki (tomasz.nowicki@linaro.org). Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsalloc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 243737363fb8..bc3f598257a2 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -106,6 +106,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) void acpi_ns_delete_node(struct acpi_namespace_node *node) { union acpi_operand_object *obj_desc; + union acpi_operand_object *next_desc; ACPI_FUNCTION_NAME(ns_delete_node); @@ -114,12 +115,13 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) acpi_ns_detach_object(node); /* - * Delete an attached data object if present (an object that was created - * and attached via acpi_attach_data). Note: After any normal object is - * detached above, the only possible remaining object is a data object. + * Delete an attached data object list if present (objects that were + * attached via acpi_attach_data). Note: After any normal object is + * detached above, the only possible remaining object(s) are data + * objects, in a linked list. */ obj_desc = node->object; - if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { + while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { /* Invoke the attached data deletion handler if present */ @@ -127,7 +129,9 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) obj_desc->data.handler(node, obj_desc->data.pointer); } + next_desc = obj_desc->common.next_object; acpi_ut_remove_reference(obj_desc); + obj_desc = next_desc; } /* Now we can delete the node */ -- cgit v1.2.3 From 3f69fe153133f781d546f0c53f7dd3889275c90d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 21 Nov 2013 12:20:06 +0800 Subject: ACPICA: Add support to delete all objects attached to the root namespace node. This fix deletes any and all objects that have been attached to the root node (via acpi_attach_data). Reported by Tomasz Nowicki. ACPICA BZ 1026. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsalloc.c | 6 ++++++ drivers/acpi/acpica/nsutils.c | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index bc3f598257a2..fd1ff54cda19 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -134,6 +134,12 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) obj_desc = next_desc; } + /* Special case for the statically allocated root node */ + + if (node == acpi_gbl_root_node) { + return; + } + /* Now we can delete the node */ (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index cc2fea94c5f0..4a0665b6bcc1 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -593,24 +593,26 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) void acpi_ns_terminate(void) { - union acpi_operand_object *obj_desc; + acpi_status status; ACPI_FUNCTION_TRACE(ns_terminate); /* - * 1) Free the entire namespace -- all nodes and objects - * - * Delete all object descriptors attached to namepsace nodes + * Free the entire namespace -- all nodes and all objects + * attached to the nodes */ acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); - /* Detach any objects attached to the root */ + /* Delete any objects attached to the root node */ - obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); - if (obj_desc) { - acpi_ns_detach_object(acpi_gbl_root_node); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_VOID; } + acpi_ns_delete_node(acpi_gbl_root_node); + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; } -- cgit v1.2.3 From 083ca8c4172585409170dac9955a1da8137fef49 Mon Sep 17 00:00:00 2001 From: Daisuke HATAYAMA Date: Tue, 19 Nov 2013 17:54:47 +0900 Subject: ACPI / sysfs: Set file size for each exposed ACPI table Currently, each of the ACPI tables exported from /sys/firmware/acpi/tables is of zero size: $ LANG=C ls -ld /sys/firmware/acpi/tables/* -r-------- 1 root root 0 Nov 19 09:48 /sys/firmware/acpi/tables/APIC -r-------- 1 root root 0 Nov 19 09:48 /sys/firmware/acpi/tables/BOOT -r-------- 1 root root 0 Nov 19 14:25 /sys/firmware/acpi/tables/DSDT -r-------- 1 root root 0 Nov 19 14:25 /sys/firmware/acpi/tables/FACP -r-------- 1 root root 0 Nov 19 14:25 /sys/firmware/acpi/tables/FACS -r-------- 1 root root 0 Nov 19 14:25 /sys/firmware/acpi/tables/MCFG -r-------- 1 root root 0 Nov 19 14:25 /sys/firmware/acpi/tables/SRAT drwxr-xr-x 2 root root 0 Nov 19 09:48 /sys/firmware/acpi/tables/dynamic/ due to which, user-land tools fail reading each table. For example: $ acpidump -f /sys/firmware/acpi/tables/SRAT Could not get input file size: /sys/firmware/acpi/tables/SRAT To deal with the issue, this patch assigns size of each ACPI table to the corresponding sysfs file. $ LANG=C ls -hld /sys/firmware/acpi/tables/* -r-------- 1 root root 94 Nov 19 16:45 /sys/firmware/acpi/tables/APIC -r-------- 1 root root 40 Nov 19 16:45 /sys/firmware/acpi/tables/BOOT -r-------- 1 root root 58K Nov 19 16:55 /sys/firmware/acpi/tables/DSDT -r-------- 1 root root 244 Nov 19 16:55 /sys/firmware/acpi/tables/FACP -r-------- 1 root root 64 Nov 19 16:55 /sys/firmware/acpi/tables/FACS -r-------- 1 root root 60 Nov 19 16:55 /sys/firmware/acpi/tables/MCFG -r-------- 1 root root 168 Nov 19 16:45 /sys/firmware/acpi/tables/SRAT drwxr-xr-x 2 root root 0 Nov 19 16:55 /sys/firmware/acpi/tables/dynamic/ Then, user-land tools work well like: $ acpidump -f /sys/firmware/acpi/tables/SRAT SRAT @ 0x0000000000000000 0000: 53 52 41 54 A8 00 00 00 02 65 56 4D 57 41 52 45 SRAT.....eVMWARE 0010: 4D 45 4D 50 4C 55 47 20 00 00 04 06 56 4D 57 20 MEMPLUG ....VMW 0020: 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 0030: 01 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .(.............. 0040: 00 00 0A 00 00 00 00 00 00 00 00 00 01 00 00 00 ................ 0050: 00 00 00 00 00 00 00 00 01 28 00 00 00 00 00 00 .........(...... 0060: 00 00 10 00 00 00 00 00 00 00 F0 BF 00 00 00 00 ................ 0070: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 0080: 01 28 00 00 00 00 00 00 00 00 00 00 01 00 00 00 .(.............. 0090: 00 00 00 40 00 00 00 00 00 00 00 00 01 00 00 00 ...@............ 00A0: 00 00 00 00 00 00 00 00 ........ Signed-off-by: HATAYAMA Daisuke Acked-by: Toshi Kani Acked-by: Zhang Rui Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index db5293650f62..45f82c751225 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -309,7 +309,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", table_attr->instance); - table_attr->attr.size = 0; + table_attr->attr.size = table_header->length; table_attr->attr.read = acpi_table_show; table_attr->attr.attr.name = table_attr->name; table_attr->attr.attr.mode = 0400; -- cgit v1.2.3 From de03beedb43fa1fd26792a4e502eeacbf5a6bade Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Thu, 21 Nov 2013 11:20:23 +0100 Subject: ACPI / sysfs: Fix incorrect ACPI tables walk in acpi_tables_sysfs_init() When executing on an ACPI Hardware Reduced hardware, all the ACPI tables are not exposed in sysfs due to the fact that FACS is silently ignored by the kernel in the ACPI hardware reduced mode and, moreover, the acpi_tables_sysfs_init() ACPI table walk is buggy and stops too soon. The acpi_tables_sysfs_init() function should rely on the acpi_status return value from acpi_get_table_by_index() to decide whether or not to stop the iteration (the walk should only be terminated when that value is AE_BAD_PARAMETER). This way, when running in an ACPI Harware Reduced environment (where the FACS table is silently ignored by the kernel) or if some ACPI tables are not correctly memory mapped or have bad checksums, it will still walk through the remaining tables that may be correct. [rjw: Changelog] Signed-off-by: Jeremy Compostella Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 45f82c751225..6dbc3ca45223 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -354,8 +354,9 @@ static int acpi_tables_sysfs_init(void) { struct acpi_table_attr *table_attr; struct acpi_table_header *table_header = NULL; - int table_index = 0; - int result; + int table_index; + acpi_status status; + int ret; tables_kobj = kobject_create_and_add("tables", acpi_kobj); if (!tables_kobj) @@ -365,33 +366,34 @@ static int acpi_tables_sysfs_init(void) if (!dynamic_tables_kobj) goto err_dynamic_tables; - do { - result = acpi_get_table_by_index(table_index, &table_header); - if (!result) { - table_index++; - table_attr = NULL; - table_attr = - kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); - if (!table_attr) - return -ENOMEM; - - acpi_table_attr_init(table_attr, table_header); - result = - sysfs_create_bin_file(tables_kobj, - &table_attr->attr); - if (result) { - kfree(table_attr); - return result; - } else - list_add_tail(&table_attr->node, - &acpi_table_attr_list); + for (table_index = 0;; table_index++) { + status = acpi_get_table_by_index(table_index, &table_header); + + if (status == AE_BAD_PARAMETER) + break; + + if (ACPI_FAILURE(status)) + continue; + + table_attr = NULL; + table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); + if (!table_attr) + return -ENOMEM; + + acpi_table_attr_init(table_attr, table_header); + ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); + if (ret) { + kfree(table_attr); + return ret; } - } while (!result); + list_add_tail(&table_attr->node, &acpi_table_attr_list); + } + kobject_uevent(tables_kobj, KOBJ_ADD); kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); - result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); + status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); - return result == AE_OK ? 0 : -EINVAL; + return ACPI_FAILURE(status) ? -EINVAL : 0; err_dynamic_tables: kobject_put(tables_kobj); err: -- cgit v1.2.3 From 91be0998578a1001db1382012676ee0a69d5cee3 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 23 Nov 2013 07:27:27 +0800 Subject: ACPI: Clean up incorrect inclusions of ACPICA headers Header file contains environemnt settings and architecture specific implementation that should be included before any other ACPICA headers in order to keep a consistent build environment for ACPICA users. The following internal ACPICA header files should be included from and should not be included by other kernel files: Clean up incorrect inclusions of these files from non-ACPICA source files. [rjw: Subject and changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/nvs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 266bc58ce0ce..386a9fe497b4 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c @@ -13,7 +13,6 @@ #include #include #include -#include /* ACPI NVS regions, APEI may use it */ -- cgit v1.2.3