From c8cefe307d79c57b32ca1d4c9ebff528f8dd914c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 14 Jun 2011 10:42:53 +0800 Subject: ACPICA: Load operator: re-instate most restrictions on incoming table signature Now, only allow "SSDT" "OEM", and a null signature. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 48db094..62365f6 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -126,12 +126,29 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } /* - * Originally, we checked the table signature for "SSDT" or "PSDT" here. - * Next, we added support for OEMx tables, signature "OEM". - * Valid tables were encountered with a null signature, so we've just - * given up on validating the signature, since it seems to be a waste - * of code. The original code was removed (05/2008). + * Validate the incoming table signature. + * + * 1) Originally, we checked the table signature for "SSDT" or "PSDT". + * 2) We added support for OEMx tables, signature "OEM". + * 3) Valid tables were encountered with a null signature, so we just + * gave up on validating the signature, (05/2008). + * 4) We encountered non-AML tables such as the MADT, which caused + * interpreter errors and kernel faults. So now, we once again allow + * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ + if ((table_desc->pointer->signature[0] != 0x00) && + (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) + && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { + ACPI_ERROR((AE_INFO, + "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx", + acpi_ut_valid_acpi_name(*(u32 *)table_desc-> + pointer-> + signature) ? table_desc-> + pointer->signature : "????", + *(u32 *)table_desc->pointer->signature)); + + return_ACPI_STATUS(AE_BAD_SIGNATURE); + } (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -- cgit v0.10.2 From f631f9cafbc47bbfe5eb2aa831cd323175298448 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 14 Jun 2011 10:44:51 +0800 Subject: ACPICA: Add missing _TDL to list of predefined names Affects both iASL and core ACPICA. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 94e73c9..c445cca 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -468,6 +468,7 @@ static const union acpi_predefined_info predefined_names[] = {{"_SWS", 0, ACPI_RTYPE_INTEGER}}, {{"_TC1", 0, ACPI_RTYPE_INTEGER}}, {{"_TC2", 0, ACPI_RTYPE_INTEGER}}, + {{"_TDL", 0, ACPI_RTYPE_INTEGER}}, {{"_TIP", 1, ACPI_RTYPE_INTEGER}}, {{"_TIV", 1, ACPI_RTYPE_INTEGER}}, {{"_TMP", 0, ACPI_RTYPE_INTEGER}}, -- cgit v0.10.2 From 80f40ce0f10e87d9a27f1e29325c6f39245fbcb1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 14 Jun 2011 10:45:57 +0800 Subject: ACPICA: Update to version 20110527 Version 20110527. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 2ed0a84..06853f7 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20110413 +#define ACPI_CA_VERSION 0x20110527 #include "actypes.h" #include "actbl.h" -- cgit v0.10.2 From d57b23ad0ca7a46931e4d98eb6b4b73b112f0969 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 4 Jul 2011 08:24:03 +0000 Subject: ACPICA: Add option to disable method return value validation and repair Runtime option can be used to disable return value repair if this is causing a problem on a particular machine. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 73863d86..76dc02f 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -126,6 +126,12 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); */ u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); +/* + * Disable runtime checking and repair of values returned by control methods. + * Use only if the repair is causing a problem on a particular machine. + */ +u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE); + /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ struct acpi_table_fadt acpi_gbl_FADT; diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 9fb03fa..607a9a0 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -193,14 +193,20 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, } /* - * 1) We have a return value, but if one wasn't expected, just exit, this is - * not a problem. For example, if the "Implicit Return" feature is - * enabled, methods will always return a value. + * Return value validation and possible repair. * - * 2) If the return value can be of any type, then we cannot perform any - * validation, exit. + * 1) Don't perform return value validation/repair if this feature + * has been disabled via a global option. + * + * 2) We have a return value, but if one wasn't expected, just exit, + * this is not a problem. For example, if the "Implicit Return" + * feature is enabled, methods will always return a value. + * + * 3) If the return value can be of any type, then we cannot perform + * any validation, just exit. */ - if ((!predefined->info.expected_btypes) || + if (acpi_gbl_disable_auto_repair || + (!predefined->info.expected_btypes) || (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { goto cleanup; } diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 06853f7..d42d7ce 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -69,6 +69,7 @@ extern u32 acpi_gbl_trace_flags; extern u32 acpi_gbl_enable_aml_debug_object; extern u8 acpi_gbl_copy_dsdt_locally; extern u8 acpi_gbl_truncate_io_addresses; +extern u8 acpi_gbl_disable_auto_repair; extern u32 acpi_current_gpe_count; extern struct acpi_table_fadt acpi_gbl_FADT; -- cgit v0.10.2 From 8f9c91273e36e5762c617c23e4fd48d5172e0dac Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Mon, 4 Jul 2011 08:36:16 +0000 Subject: ACPICA: Do not repair _TSS return package if _PSS is present We can only sort the _TSS return package if there is no _PSS in the same scope. This is because if _PSS is present, the ACPI specification dictates that the _TSS Power Dissipation field is to be ignored, and therefore some BIOSs leave garbage values in the _TSS Power field(s). In this case, it is best to just return the _TSS package as-is. Reported-by: Fenghua Yu Signed-off-by: Fenghua Yu Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index c7f743c..5552125 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -357,6 +357,7 @@ struct acpi_predefined_data { char *pathname; const union acpi_predefined_info *predefined; union acpi_operand_object *parent_package; + struct acpi_namespace_node *node; u32 flags; u8 node_flags; }; diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 607a9a0..c845c80 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -218,6 +218,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, goto cleanup; } data->predefined = predefined; + data->node = node; data->node_flags = node->flags; data->pathname = pathname; diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 973883b..024c4f2 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -503,6 +503,21 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data, { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; + struct acpi_namespace_node *node; + + /* + * We can only sort the _TSS return package if there is no _PSS in the + * same scope. This is because if _PSS is present, the ACPI specification + * dictates that the _TSS Power Dissipation field is to be ignored, and + * therefore some BIOSs leave garbage values in the _TSS Power field(s). + * In this case, it is best to just return the _TSS package as-is. + * (May, 2011) + */ + status = + acpi_ns_get_node(data->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_SUCCESS(status)) { + return (AE_OK); + } status = acpi_ns_check_sorted_list(data, return_object, 5, 1, ACPI_SORT_DESCENDING, -- cgit v0.10.2 From 3eb208f0a36cf7a86953afa7a4eb6776294e6768 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 4 Jul 2011 08:38:51 +0000 Subject: ACPICA: Update to version 20110623 Version 20110623. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index d42d7ce..f554a93 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20110527 +#define ACPI_CA_VERSION 0x20110623 #include "actypes.h" #include "actbl.h" -- cgit v0.10.2 From 1dd5c715e5b7524da8c1030f5cf1ea903e45c457 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 1 Jul 2011 16:03:15 +0800 Subject: ACPI / SBS: Add getting state operation in the acpi_sbs_battery_get_property() https://bugzilla.kernel.org/show_bug.cgi?id=24492 Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 51ae379..01dad1b 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -130,6 +130,9 @@ struct acpi_sbs { #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) +static int acpi_sbs_remove(struct acpi_device *device, int type); +static int acpi_battery_get_state(struct acpi_battery *battery); + static inline int battery_scale(int log) { int scale = 1; @@ -195,6 +198,8 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT) return -ENODEV; + + acpi_battery_get_state(battery); switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->rate_now < 0) @@ -903,8 +908,6 @@ static void acpi_sbs_callback(void *context) } } -static int acpi_sbs_remove(struct acpi_device *device, int type); - static int acpi_sbs_add(struct acpi_device *device) { struct acpi_sbs *sbs; -- cgit v0.10.2 From e4108292cc5b5ca07abc83af31a78338362810ca Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 1 Jul 2011 16:03:39 +0800 Subject: ACPI / SBS: Correct the value of power_now and power_avg in the sysfs https://bugzilla.kernel.org/show_bug.cgi?id=24492 Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 01dad1b..c517ec8 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -230,11 +230,17 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_POWER_NOW: val->intval = abs(battery->rate_now) * acpi_battery_ipscale(battery) * 1000; + val->intval *= (acpi_battery_mode(battery)) ? + (battery->voltage_now * + acpi_battery_vscale(battery) / 1000) : 1; break; case POWER_SUPPLY_PROP_CURRENT_AVG: case POWER_SUPPLY_PROP_POWER_AVG: val->intval = abs(battery->rate_avg) * acpi_battery_ipscale(battery) * 1000; + val->intval *= (acpi_battery_mode(battery)) ? + (battery->voltage_now * + acpi_battery_vscale(battery) / 1000) : 1; break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = battery->state_of_charge; -- cgit v0.10.2 From ae6f61870490c10a0b0436e5afffa00c9dacffef Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:32:40 +0800 Subject: ACPI / Battery: Add the power unit macro This patch is cosmetic only, and makes no functional change. Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index fcc13ac..611434f 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -55,6 +55,9 @@ #define ACPI_BATTERY_NOTIFY_INFO 0x81 #define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 +/* Battery power unit: 0 means mW, 1 means mA */ +#define ACPI_BATTERY_POWER_UNIT_MA 1 + #define _COMPONENT ACPI_BATTERY_COMPONENT ACPI_MODULE_NAME("battery"); @@ -301,7 +304,8 @@ static enum power_supply_property energy_battery_props[] = { #ifdef CONFIG_ACPI_PROCFS_POWER inline char *acpi_battery_units(struct acpi_battery *battery) { - return (battery->power_unit)?"mA":"mW"; + return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? + "mA" : "mW"; } #endif @@ -544,7 +548,7 @@ static int sysfs_add_battery(struct acpi_battery *battery) { int result; - if (battery->power_unit) { + if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { battery->bat.properties = charge_battery_props; battery->bat.num_properties = ARRAY_SIZE(charge_battery_props); @@ -575,7 +579,8 @@ static void sysfs_remove_battery(struct acpi_battery *battery) static void acpi_battery_quirks(struct acpi_battery *battery) { - if (dmi_name_in_vendors("Acer") && battery->power_unit) { + if (dmi_name_in_vendors("Acer") && + battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags); } } -- cgit v0.10.2 From 55003b2105a4578736f3e868fbaa889bb1ff3ce0 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:33:12 +0800 Subject: ACPI / Battery: Change 16-bit signed negative battery current into correct value This patch is for some machines which report the battery current as a 16-bit signed negative when it is charging. This is caused by DSDT bug. The commit bc76f90b8a5cf4aceedf210d08d5e8292f820cec has resolved the problem for Acer laptops. But some other machines also have such problem. https://bugzilla.kernel.org/show_bug.cgi?id=33722 Since it is improper that the current is above 32A on laptops whether on AC or on battery, this patch is to check the current and take its absolute value as current and producing a message when it is negative in s16. Remove Acer quirk, as this workaround handles Acer too. Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 611434f..ff1ff70 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -94,11 +94,6 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids); enum { ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_XINFO_PRESENT, - /* For buggy DSDTs that report negative 16-bit values for either - * charging or discharging current and/or report 0 as 65536 - * due to bad math. - */ - ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, }; @@ -465,9 +460,17 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->update_time = jiffies; kfree(buffer.pointer); - if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) && - battery->rate_now != -1) + /* For buggy DSDTs that report negative 16-bit values for either + * charging or discharging current and/or report 0 as 65536 + * due to bad math. + */ + if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA && + battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && + (s16)(battery->rate_now) < 0) { battery->rate_now = abs((s16)battery->rate_now); + printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate" + " invalid.\n"); + } if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) && battery->capacity_now >= 0 && battery->capacity_now <= 100) @@ -577,14 +580,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) battery->bat.dev = NULL; } -static void acpi_battery_quirks(struct acpi_battery *battery) -{ - if (dmi_name_in_vendors("Acer") && - battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { - set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags); - } -} - /* * According to the ACPI spec, some kinds of primary batteries can * report percentage battery remaining capacity directly to OS. @@ -628,7 +623,6 @@ static int acpi_battery_update(struct acpi_battery *battery) result = acpi_battery_get_info(battery); if (result) return result; - acpi_battery_quirks(battery); acpi_battery_init_alarm(battery); } if (!battery->bat.dev) -- cgit v0.10.2 From 7b78622d0f9df9f274a319eea1494240119d3734 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:33:27 +0800 Subject: ACPI / Battery: Rename acpi_battery_quirks2 with acpi_battery_quirks This patch is cosmetic only, and makes no functional change. Since the acpi_battery_quirks has been deleted, rename acpi_battery_quirks2 with acpi_battery_quirks to clean the code. Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ff1ff70..ba7926fc 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -592,7 +592,7 @@ static void sysfs_remove_battery(struct acpi_battery *battery) * * Handle this correctly so that they won't break userspace. */ -static void acpi_battery_quirks2(struct acpi_battery *battery) +static void acpi_battery_quirks(struct acpi_battery *battery) { if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) return ; @@ -628,7 +628,7 @@ static int acpi_battery_update(struct acpi_battery *battery) if (!battery->bat.dev) sysfs_add_battery(battery); result = acpi_battery_get_state(battery); - acpi_battery_quirks2(battery); + acpi_battery_quirks(battery); return result; } -- cgit v0.10.2 From d5a5911b3278bad6515a9958f7318f74d534ef64 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:33:40 +0800 Subject: ACPI / Battery: Add the hibernation process in the battery_notify() The Commit 25be58215 has added a PM notifier to refresh the sys in order to deal with the unit change of the Battery Present Rate. But it just consided the suspend situation. The problem also will happen during the hibernation according the bug 28192. https://bugzilla.kernel.org/show_bug.cgi?id=28192 This patch adds the hibernation process and fix the bug. Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ba7926fc..2fe7cfd 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -947,6 +947,7 @@ static int battery_notify(struct notifier_block *nb, struct acpi_battery *battery = container_of(nb, struct acpi_battery, pm_nb); switch (mode) { + case PM_POST_HIBERNATION: case PM_POST_SUSPEND: sysfs_remove_battery(battery); sysfs_add_battery(battery); -- cgit v0.10.2 From 6e17fb6aa1a67afa1827ae317c3594040f055730 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:33:58 +0800 Subject: ACPI / Battery: Add the check before refresh sysfs in the battery_notify() In the commit 25be5821, add the refresh sysfs when system resumes from suspending. But it didn't check that the battery exists. This will cause battery sysfs files added when the battery doesn't exist. This patch add the check before refreshing. https://bugzilla.kernel.org/show_bug.cgi?id=35642 Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2fe7cfd..4ba339d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -949,8 +949,10 @@ static int battery_notify(struct notifier_block *nb, switch (mode) { case PM_POST_HIBERNATION: case PM_POST_SUSPEND: - sysfs_remove_battery(battery); - sysfs_add_battery(battery); + if (battery->bat.dev) { + sysfs_remove_battery(battery); + sysfs_add_battery(battery); + } break; } -- cgit v0.10.2 From 9c921c22a7f33397a6774d7fa076db9b6a0fd669 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 30 Jun 2011 11:34:12 +0800 Subject: ACPI / Battery: Resolve the race condition in the sysfs_remove_battery() Use battery->lock in sysfs_remove_battery() to make checking, removing, and clearing bat.dev atomic. This is necessary because sysfs_remove_battery() may be invoked concurrently from different paths. https://bugzilla.kernel.org/show_bug.cgi?id=35642 Signed-off-by: Lan Tianyu Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 4ba339d..40bf01d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -573,11 +573,16 @@ static int sysfs_add_battery(struct acpi_battery *battery) static void sysfs_remove_battery(struct acpi_battery *battery) { - if (!battery->bat.dev) + mutex_lock(&battery->lock); + if (!battery->bat.dev) { + mutex_unlock(&battery->lock); return; + } + device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); battery->bat.dev = NULL; + mutex_unlock(&battery->lock); } /* -- cgit v0.10.2 From e545b55a1e980cbb6a158886286106bbf39722b1 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Sun, 19 Jun 2011 18:51:37 -0500 Subject: ACPI: fix 80 char overflow Trivial fix for 80 char line overflow in drivers/acpi/pci_root.c Signed-off-by: Jon Mason Signed-off-by: Len Brown diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d06078d..2672c79 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -485,7 +485,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) root->secondary.end = 0xFF; printk(KERN_WARNING FW_BUG PREFIX "no secondary bus range in _CRS\n"); - status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); + status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, + NULL, &bus); if (ACPI_SUCCESS(status)) root->secondary.start = bus; else if (status == AE_NOT_FOUND) -- cgit v0.10.2 From d7f6169a0d32002657886fee561c641acddb9a75 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Fri, 15 Jul 2011 14:52:30 +0200 Subject: ACPI: fix CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS The following was observed by Steve Rostedt on 3.0.0-rc5 Backtrace: irq 16: nobody cared (try booting with the "irqpoll" option) Pid: 65, comm: irq/16-uhci_hcd Not tainted 3.0.0-rc5-test+ #94 Call Trace: [] __report_bad_irq+0x37/0xc1 [] note_interrupt+0x14e/0x1c9 [] ? irq_thread_fn+0x3c/0x3c [] irq_thread+0xf6/0x1b1 [] ? irq_finalize_oneshot+0xb3/0xb3 [] kthread+0x9f/0xa7 [] kernel_thread_helper+0x4/0x10 [] ? finish_task_switch+0x7b/0xc0 [] ? retint_restore_args+0x13/0x13 [] ? __init_kthread_worker+0x5a/0x5a [] ? gs_change+0x13/0x13 handlers: [] irq_default_primary_handler threaded [] usb_hcd_irq [] irq_default_primary_handler threaded [] usb_hcd_irq Disabling IRQ #16 The problem being that a device triggers boot interrupts (due to threaded interrupt handling and masking of the IO-APIC), which are forwarded to the PIRQ line of the device. These interrupts are not handled on the PIRQ line because the interrupt handler is not present there. This should have already been fixed by CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS. However some parts of the quirk got lost in the ACPI merge. This is a resent of the patch proposed in 2009. See http://lkml.org/lkml/2009/9/7/192 Signed-off-by: Stefan Assmann Tested-by: Steven Rostedt Signed-off-by: Len Brown diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index f907cfb..7f9eba9 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -303,6 +303,61 @@ void acpi_pci_irq_del_prt(struct pci_bus *bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +#ifdef CONFIG_X86_IO_APIC +extern int noioapicquirk; +extern int noioapicreroute; + +static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) +{ + struct pci_bus *bus_it; + + for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { + if (!bus_it->self) + return 0; + if (bus_it->self->irq_reroute_variant) + return bus_it->self->irq_reroute_variant; + } + return 0; +} + +/* + * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ + * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does + * during interrupt handling). When this INTx generation cannot be disabled, + * we reroute these interrupts to their legacy equivalent to get rid of + * spurious interrupts. + */ +static int acpi_reroute_boot_interrupt(struct pci_dev *dev, + struct acpi_prt_entry *entry) +{ + if (noioapicquirk || noioapicreroute) { + return 0; + } else { + switch (bridge_has_boot_interrupt_variant(dev->bus)) { + case 0: + /* no rerouting necessary */ + return 0; + case INTEL_IRQ_REROUTE_VARIANT: + /* + * Remap according to INTx routing table in 6700PXH + * specs, intel order number 302628-002, section + * 2.15.2. Other chipsets (80332, ...) have the same + * mapping and are handled here as well. + */ + dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy " + "IRQ %d\n", entry->index, + (entry->index % 4) + 16); + entry->index = (entry->index % 4) + 16; + return 1; + default: + dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy " + "IRQ: unknown mapping\n", entry->index); + return -1; + } + } +} +#endif /* CONFIG_X86_IO_APIC */ + static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { struct acpi_prt_entry *entry; @@ -311,6 +366,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) entry = acpi_pci_irq_find_prt_entry(dev, pin); if (entry) { +#ifdef CONFIG_X86_IO_APIC + acpi_reroute_boot_interrupt(dev, entry); +#endif /* CONFIG_X86_IO_APIC */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); return entry; -- cgit v0.10.2 From 9c8b04be443b33939f374a811c82abeebe0a61d1 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 25 Jun 2011 21:07:52 +0400 Subject: ACPI: constify ops structs Structs battery_file, acpi_dock_ops, file_operations, thermal_cooling_device_ops, thermal_zone_device_ops, kernel_param_ops are not changed in runtime. It is safe to make them const. register_hotplug_dock_device() was altered to take const "ops" argument to respect acpi_dock_ops' const notion. Signed-off-by: Vasiliy Kulikov Acked-by: Jeff Garzik Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index fcc13ac..746b475 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -863,7 +863,7 @@ DECLARE_FILE_FUNCTIONS(alarm); }, \ } -static struct battery_file { +static const struct battery_file { struct file_operations ops; mode_t mode; const char *name; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1864ad3..19a6113 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -77,7 +77,7 @@ struct dock_dependent_device { struct list_head list; struct list_head hotplug_list; acpi_handle handle; - struct acpi_dock_ops *ops; + const struct acpi_dock_ops *ops; void *context; }; @@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); * the dock driver after _DCK is executed. */ int -register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, +register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, void *context) { struct dock_dependent_device *dd; diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index 05b4420..22f918b 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c @@ -92,7 +92,7 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, return count; } -static struct file_operations acpi_ec_io_ops = { +static const struct file_operations acpi_ec_io_ops = { .owner = THIS_MODULE, .open = acpi_ec_open_io, .read = acpi_ec_read_io, diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 467479f..0f0356c 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -110,7 +110,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) return result; } -static struct thermal_cooling_device_ops fan_cooling_ops = { +static const struct thermal_cooling_device_ops fan_cooling_ops = { .get_max_state = fan_get_max_state, .get_cur_state = fan_get_cur_state, .set_cur_state = fan_set_cur_state, diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 79cb653..870550d 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -244,7 +244,7 @@ processor_set_cur_state(struct thermal_cooling_device *cdev, return result; } -struct thermal_cooling_device_ops processor_cooling_ops = { +const struct thermal_cooling_device_ops processor_cooling_ops = { .get_max_state = processor_get_max_state, .get_cur_state = processor_get_cur_state, .set_cur_state = processor_set_cur_state, diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 77255f2..c538d0e 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -149,12 +149,12 @@ static int param_get_debug_level(char *buffer, const struct kernel_param *kp) return result; } -static struct kernel_param_ops param_ops_debug_layer = { +static const struct kernel_param_ops param_ops_debug_layer = { .set = param_set_uint, .get = param_get_debug_layer, }; -static struct kernel_param_ops param_ops_debug_level = { +static const struct kernel_param_ops param_ops_debug_level = { .set = param_set_uint, .get = param_get_debug_level, }; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 2607e17..48fbc64 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -812,7 +812,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, thermal_zone_unbind_cooling_device); } -static struct thermal_zone_device_ops acpi_thermal_zone_ops = { +static const struct thermal_zone_device_ops acpi_thermal_zone_ops = { .bind = acpi_thermal_bind_cooling_device, .unbind = acpi_thermal_unbind_cooling_device, .get_temp = thermal_get_temp, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index db39e9e..c6f9ef8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -308,7 +308,7 @@ video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long st return acpi_video_device_lcd_set_level(video, level); } -static struct thermal_cooling_device_ops video_cooling_ops = { +static const struct thermal_cooling_device_ops video_cooling_ops = { .get_max_state = video_get_max_state, .get_cur_state = video_get_cur_state, .set_cur_state = video_set_cur_state, diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index a791b8ce..993d406 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -218,12 +218,12 @@ static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) ata_acpi_uevent(dev->link->ap, dev, event); } -static struct acpi_dock_ops ata_acpi_dev_dock_ops = { +static const struct acpi_dock_ops ata_acpi_dev_dock_ops = { .handler = ata_acpi_dev_notify_dock, .uevent = ata_acpi_dev_uevent, }; -static struct acpi_dock_ops ata_acpi_ap_dock_ops = { +static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { .handler = ata_acpi_ap_notify_dock, .uevent = ata_acpi_ap_uevent, }; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a70fa89..2202857 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -110,7 +110,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, } -static struct acpi_dock_ops acpiphp_dock_ops = { +static const struct acpi_dock_ops acpiphp_dock_ops = { .handler = handle_hotplug_event_func, }; diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 3090471..e49c36d 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -128,7 +128,7 @@ extern int is_dock_device(acpi_handle handle); extern int register_dock_notifier(struct notifier_block *nb); extern void unregister_dock_notifier(struct notifier_block *nb); extern int register_hotplug_dock_device(acpi_handle handle, - struct acpi_dock_ops *ops, + const struct acpi_dock_ops *ops, void *context); extern void unregister_hotplug_dock_device(acpi_handle handle); #else diff --git a/include/acpi/processor.h b/include/acpi/processor.h index ba4928c..67055f1 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -337,7 +337,7 @@ extern struct cpuidle_driver acpi_idle_driver; /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); -extern struct thermal_cooling_device_ops processor_cooling_ops; +extern const struct thermal_cooling_device_ops processor_cooling_ops; #ifdef CONFIG_CPU_FREQ void acpi_thermal_cpufreq_init(void); void acpi_thermal_cpufreq_exit(void); -- cgit v0.10.2 From 4996c02306a25def1d352ec8e8f48895bbc7dea9 Mon Sep 17 00:00:00 2001 From: Takao Indoh Date: Thu, 14 Jul 2011 18:05:21 -0400 Subject: ACPI: introduce "acpi_rsdp=" parameter for kdump There is a problem with putting the first kernel in EFI virtual mode, it is that when the second kernel comes up it tries to initialize the EFI again and once we have put EFI in virtual mode we can not really do that. Actually, EFI is not necessary for kdump, we can boot the second kernel with "noefi" parameter, but the boot will mostly fail because 2nd kernel cannot find RSDP. In this situation, we introduced "acpi_rsdp=" kernel parameter, so that kexec-tools can pass the "noefi acpi_rsdp=X" to the second kernel to make kdump works. The physical address of the RSDP can be got from sysfs(/sys/firmware/efi/systab). Signed-off-by: Takao Indoh Reviewed-by: WANG Cong Reviewed-by: Konrad Rzeszutek Wilk Signed-off-by: Len Brown diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index aa47be7..37713bc 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -163,6 +163,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. See also Documentation/power/pm.txt, pci=noacpi + acpi_rsdp= [ACPI,EFI,KEXEC] + Pass the RSDP address to the kernel, mostly used + on machines running EFI runtime service to boot the + second kernel for kdump. + acpi_apic_instance= [ACPI, IOAPIC] Format: 2: use 2nd APIC table, if available diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 52ca964..27cd140 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -237,8 +237,23 @@ void acpi_os_vprintf(const char *fmt, va_list args) #endif } +#ifdef CONFIG_KEXEC +static unsigned long acpi_rsdp; +static int __init setup_acpi_rsdp(char *arg) +{ + acpi_rsdp = simple_strtoul(arg, NULL, 16); + return 0; +} +early_param("acpi_rsdp", setup_acpi_rsdp); +#endif + acpi_physical_address __init acpi_os_get_root_pointer(void) { +#ifdef CONFIG_KEXEC + if (acpi_rsdp) + return acpi_rsdp; +#endif + if (efi_enabled) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; -- cgit v0.10.2 From e80bba4b5108c6479379740201b0a5d9da5ffbac Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 12 Jul 2011 09:03:28 +0100 Subject: ACPI / Battery: avoid acpi_battery_add() use-after-free When acpi_battery_add_fs() fails the error handling code does not clean up completely. Moreover, it does not return resulting in a use-after-free. Signed-off-by: Stefan Hajnoczi Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 40bf01d..c771768 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -986,21 +986,27 @@ static int acpi_battery_add(struct acpi_device *device) #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); #endif - if (!result) { - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", - ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), - device->status.battery_present ? "present" : "absent"); - } else { + if (result) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif - kfree(battery); + goto fail; } + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present ? "present" : "absent"); + battery->pm_nb.notifier_call = battery_notify; register_pm_notifier(&battery->pm_nb); return result; + +fail: + sysfs_remove_battery(battery); + mutex_destroy(&battery->lock); + kfree(battery); + return result; } static int acpi_battery_remove(struct acpi_device *device, int type) -- cgit v0.10.2 From eb03cb02b74df6dd0b653d5f6d976f16a434dfaf Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 12 Jul 2011 09:03:29 +0100 Subject: ACPI / Battery: propagate sysfs error in acpi_battery_add() Make sure the error return from sysfs_add_battery() is checked and propagated out from acpi_battery_add(). Signed-off-by: Stefan Hajnoczi Signed-off-by: Len Brown diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c771768..ffce2f0 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -630,8 +630,11 @@ static int acpi_battery_update(struct acpi_battery *battery) return result; acpi_battery_init_alarm(battery); } - if (!battery->bat.dev) - sysfs_add_battery(battery); + if (!battery->bat.dev) { + result = sysfs_add_battery(battery); + if (result) + return result; + } result = acpi_battery_get_state(battery); acpi_battery_quirks(battery); return result; @@ -982,7 +985,9 @@ static int acpi_battery_add(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, "_BIX", &handle))) set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); - acpi_battery_update(battery); + result = acpi_battery_update(battery); + if (result) + goto fail; #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); #endif -- cgit v0.10.2 From bb0c5ed6ec523199e34e81dcef8e987507553b63 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 30 Jul 2011 01:40:48 -0400 Subject: ACPI: DMI workaround for Asus A8N-SLI Premium and Asus A8N-SLI DELUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMI workaround for A8N-SLI Premium and A8N-SLI DELUXE to enable the s3 suspend old ordering. http://bugzilla.kernel.org/show_bug.cgi?id=9528 Tested-by: Heiko Ettelbrück Tested-by: Brian Beardall Signed-off-by: Zhang Rui Signed-off-by: Len Brown diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 6c94960..3ed80b2 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -428,6 +428,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI DELUXE", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI Premium", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v0.10.2 From 8997621bb2daaf19a4e9d82f118224159d8054e2 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 2 Aug 2011 00:45:48 -0400 Subject: ACPI print OSI(Linux) warning only once This message gets repeated on some machines: https://bugzilla.kernel.org/show_bug.cgi?id=29292 Signed-off-by: Len Brown diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 52ca964..3765980 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -155,7 +155,7 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) { if (!strcmp("Linux", interface)) { - printk(KERN_NOTICE FW_BUG PREFIX + printk_once(KERN_NOTICE FW_BUG PREFIX "BIOS _OSI(Linux) query %s%s\n", osi_linux.enable ? "honored" : "ignored", osi_linux.cmdline ? " via cmdline" : -- cgit v0.10.2 From ab92402af04c151c26541eb28e1c26286a429db5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Jul 2011 13:48:40 -0700 Subject: thermal: hide CONFIG_THERMAL_HWMON It's about time to revert 16d752397301b9 ("thermal: Create CONFIG_THERMAL_HWMON=n"). Anybody running a kernel >= 2.6.40 would also be running a recent enough version of lm-sensors. Actually having CONFIG_THERMAL_HWMON is pretty convenient so instead of dropping it, we keep it but hide it. Signed-off-by: Jean Delvare Cc: Rene Herman Acked-by: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Len Brown diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b1c921c..951143d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -310,15 +310,6 @@ Who: Ravikiran Thirumalai --------------------------- -What: CONFIG_THERMAL_HWMON -When: January 2009 -Why: This option was introduced just to allow older lm-sensors userspace - to keep working over the upgrade to 2.6.26. At the scheduled time of - removal fixed lm-sensors (2.x or 3.x) should be readily available. -Who: Rene Herman - ---------------------------- - What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS (in net/core/net-sysfs.c) When: After the only user (hal) has seen a release with the patches diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index bf7c687..f7f71b2 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -14,11 +14,7 @@ menuconfig THERMAL If you want this support, you should say Y or M here. config THERMAL_HWMON - bool "Hardware monitoring support" + bool depends on THERMAL depends on HWMON=y || HWMON=THERMAL - help - The generic thermal sysfs driver's hardware monitoring support - requires a 2.10.7/3.0.2 or later lm-sensors userspace. - - Say Y if your user-space is new enough. + default y -- cgit v0.10.2 From 0d97d7a494d43be77f57e688369be0aae33d1ade Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Jul 2011 13:48:41 -0700 Subject: thermal: split hwmon lookup to a separate function We'll soon need to reuse it. Signed-off-by: Jean Delvare Cc: Rene Herman Acked-by: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Len Brown diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 0b1c82a..b6353d6 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -469,22 +469,35 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, } -static int -thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +static struct thermal_hwmon_device * +thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz) { struct thermal_hwmon_device *hwmon; - int new_hwmon_device = 1; - int result; mutex_lock(&thermal_list_lock); list_for_each_entry(hwmon, &thermal_hwmon_list, node) if (!strcmp(hwmon->type, tz->type)) { - new_hwmon_device = 0; mutex_unlock(&thermal_list_lock); - goto register_sys_interface; + return hwmon; } mutex_unlock(&thermal_list_lock); + return NULL; +} + +static int +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +{ + struct thermal_hwmon_device *hwmon; + int new_hwmon_device = 1; + int result; + + hwmon = thermal_hwmon_lookup_by_type(tz); + if (hwmon) { + new_hwmon_device = 0; + goto register_sys_interface; + } + hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); if (!hwmon) return -ENOMEM; -- cgit v0.10.2 From 31f5396ad3bde23c8416e8d23ba425e27f413314 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Jul 2011 13:48:42 -0700 Subject: thermal: make THERMAL_HWMON implementation fully internal THERMAL_HWMON is implemented inside the thermal_sys driver and has no effect on drivers implementing thermal zones, so they shouldn't see anything related to it in . Making the THERMAL_HWMON implementation fully internal has two advantages beyond the cleaner design: * This avoids rebuilding all thermal drivers if the THERMAL_HWMON implementation changes, or if CONFIG_THERMAL_HWMON gets enabled or disabled. * This avoids breaking the thermal kABI in these cases too, which should make distributions happy. The only drawback I can see is slightly higher memory fragmentation, as the number of kzalloc() calls will increase by one per thermal zone. But I doubt it will be a problem in practice, as I've never seen a system with more than two thermal zones. Signed-off-by: Jean Delvare Cc: Rene Herman Acked-by: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Len Brown diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index b6353d6..708f8e9 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -420,6 +420,29 @@ thermal_cooling_device_trip_point_show(struct device *dev, /* hwmon sys I/F */ #include + +/* thermal zone devices with the same type share one hwmon device */ +struct thermal_hwmon_device { + char type[THERMAL_NAME_LENGTH]; + struct device *device; + int count; + struct list_head tz_list; + struct list_head node; +}; + +struct thermal_hwmon_attr { + struct device_attribute attr; + char name[16]; +}; + +/* one temperature input for each thermal zone */ +struct thermal_hwmon_temp { + struct list_head hwmon_node; + struct thermal_zone_device *tz; + struct thermal_hwmon_attr temp_input; /* hwmon sys attr */ + struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */ +}; + static LIST_HEAD(thermal_hwmon_list); static ssize_t @@ -437,9 +460,10 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) int ret; struct thermal_hwmon_attr *hwmon_attr = container_of(attr, struct thermal_hwmon_attr, attr); - struct thermal_zone_device *tz - = container_of(hwmon_attr, struct thermal_zone_device, + struct thermal_hwmon_temp *temp + = container_of(hwmon_attr, struct thermal_hwmon_temp, temp_input); + struct thermal_zone_device *tz = temp->tz; ret = tz->ops->get_temp(tz, &temperature); @@ -455,9 +479,10 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, { struct thermal_hwmon_attr *hwmon_attr = container_of(attr, struct thermal_hwmon_attr, attr); - struct thermal_zone_device *tz - = container_of(hwmon_attr, struct thermal_zone_device, + struct thermal_hwmon_temp *temp + = container_of(hwmon_attr, struct thermal_hwmon_temp, temp_crit); + struct thermal_zone_device *tz = temp->tz; long temperature; int ret; @@ -485,10 +510,29 @@ thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz) return NULL; } +/* Find the temperature input matching a given thermal zone */ +static struct thermal_hwmon_temp * +thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon, + const struct thermal_zone_device *tz) +{ + struct thermal_hwmon_temp *temp; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(temp, &hwmon->tz_list, hwmon_node) + if (temp->tz == tz) { + mutex_unlock(&thermal_list_lock); + return temp; + } + mutex_unlock(&thermal_list_lock); + + return NULL; +} + static int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) { struct thermal_hwmon_device *hwmon; + struct thermal_hwmon_temp *temp; int new_hwmon_device = 1; int result; @@ -515,30 +559,36 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) goto free_mem; register_sys_interface: - tz->hwmon = hwmon; + temp = kzalloc(sizeof(struct thermal_hwmon_temp), GFP_KERNEL); + if (!temp) { + result = -ENOMEM; + goto unregister_name; + } + + temp->tz = tz; hwmon->count++; - snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, + snprintf(temp->temp_input.name, THERMAL_NAME_LENGTH, "temp%d_input", hwmon->count); - tz->temp_input.attr.attr.name = tz->temp_input.name; - tz->temp_input.attr.attr.mode = 0444; - tz->temp_input.attr.show = temp_input_show; - sysfs_attr_init(&tz->temp_input.attr.attr); - result = device_create_file(hwmon->device, &tz->temp_input.attr); + temp->temp_input.attr.attr.name = temp->temp_input.name; + temp->temp_input.attr.attr.mode = 0444; + temp->temp_input.attr.show = temp_input_show; + sysfs_attr_init(&temp->temp_input.attr.attr); + result = device_create_file(hwmon->device, &temp->temp_input.attr); if (result) - goto unregister_name; + goto free_temp_mem; if (tz->ops->get_crit_temp) { unsigned long temperature; if (!tz->ops->get_crit_temp(tz, &temperature)) { - snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, + snprintf(temp->temp_crit.name, THERMAL_NAME_LENGTH, "temp%d_crit", hwmon->count); - tz->temp_crit.attr.attr.name = tz->temp_crit.name; - tz->temp_crit.attr.attr.mode = 0444; - tz->temp_crit.attr.show = temp_crit_show; - sysfs_attr_init(&tz->temp_crit.attr.attr); + temp->temp_crit.attr.attr.name = temp->temp_crit.name; + temp->temp_crit.attr.attr.mode = 0444; + temp->temp_crit.attr.show = temp_crit_show; + sysfs_attr_init(&temp->temp_crit.attr.attr); result = device_create_file(hwmon->device, - &tz->temp_crit.attr); + &temp->temp_crit.attr); if (result) goto unregister_input; } @@ -547,13 +597,15 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) mutex_lock(&thermal_list_lock); if (new_hwmon_device) list_add_tail(&hwmon->node, &thermal_hwmon_list); - list_add_tail(&tz->hwmon_node, &hwmon->tz_list); + list_add_tail(&temp->hwmon_node, &hwmon->tz_list); mutex_unlock(&thermal_list_lock); return 0; unregister_input: - device_remove_file(hwmon->device, &tz->temp_input.attr); + device_remove_file(hwmon->device, &temp->temp_input.attr); + free_temp_mem: + kfree(temp); unregister_name: if (new_hwmon_device) { device_remove_file(hwmon->device, &dev_attr_name); @@ -569,15 +621,30 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) static void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) { - struct thermal_hwmon_device *hwmon = tz->hwmon; + struct thermal_hwmon_device *hwmon; + struct thermal_hwmon_temp *temp; + + hwmon = thermal_hwmon_lookup_by_type(tz); + if (unlikely(!hwmon)) { + /* Should never happen... */ + dev_dbg(&tz->device, "hwmon device lookup failed!\n"); + return; + } + + temp = thermal_hwmon_lookup_temp(hwmon, tz); + if (unlikely(!temp)) { + /* Should never happen... */ + dev_dbg(&tz->device, "temperature input lookup failed!\n"); + return; + } - tz->hwmon = NULL; - device_remove_file(hwmon->device, &tz->temp_input.attr); + device_remove_file(hwmon->device, &temp->temp_input.attr); if (tz->ops->get_crit_temp) - device_remove_file(hwmon->device, &tz->temp_crit.attr); + device_remove_file(hwmon->device, &temp->temp_crit.attr); mutex_lock(&thermal_list_lock); - list_del(&tz->hwmon_node); + list_del(&temp->hwmon_node); + kfree(temp); if (!list_empty(&hwmon->tz_list)) { mutex_unlock(&thermal_list_lock); return; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index d3ec89f..47b4a27 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -85,22 +85,6 @@ struct thermal_cooling_device { ((long)t-2732+5)/10 : ((long)t-2732-5)/10) #define CELSIUS_TO_KELVIN(t) ((t)*10+2732) -#if defined(CONFIG_THERMAL_HWMON) -/* thermal zone devices with the same type share one hwmon device */ -struct thermal_hwmon_device { - char type[THERMAL_NAME_LENGTH]; - struct device *device; - int count; - struct list_head tz_list; - struct list_head node; -}; - -struct thermal_hwmon_attr { - struct device_attribute attr; - char name[16]; -}; -#endif - struct thermal_zone_device { int id; char type[THERMAL_NAME_LENGTH]; @@ -120,12 +104,6 @@ struct thermal_zone_device { struct mutex lock; /* protect cooling devices list */ struct list_head node; struct delayed_work poll_queue; -#if defined(CONFIG_THERMAL_HWMON) - struct list_head hwmon_node; - struct thermal_hwmon_device *hwmon; - struct thermal_hwmon_attr temp_input; /* hwmon sys attr */ - struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */ -#endif }; /* Adding event notification support elements */ #define THERMAL_GENL_FAMILY_NAME "thermal_event" -- cgit v0.10.2 From f52e00c668669c9c290e84adf859c76db6d92a5a Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Thu, 28 Jul 2011 13:48:43 -0700 Subject: ACPI: remove NID_INVAL b552a8c56db8 ("ACPI: remove NID_INVAL") removed the left over uses of NID_INVAL, but didn't actually remove the definition. Remove it. Signed-off-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Len Brown diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 1deb2a7..2312e85 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -238,7 +238,6 @@ extern int acpi_paddr_to_node(u64 start_addr, u64 size); extern int pnpacpi_disabled; #define PXM_INVAL (-1) -#define NID_INVAL (-1) int acpi_check_resource_conflict(const struct resource *res); -- cgit v0.10.2 From aa165971c2923d05988f920c978e438dbc7b0de6 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Jul 2011 13:48:43 -0700 Subject: ACPI: add missing _OSI strings Linux supports some optional features, but it should notify the BIOS about them via the _OSI method. Currently Linux doesn't notify any, which might make such features not work because the BIOS doesn't know about them. Jarosz has a system which needs this to make ACPI processor aggregator device work. Reported-by: "Jarosz, Sebastian" Signed-off-by: Shaohua Li Acked-by: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Len Brown diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 372f9b7..0e47857 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1083,7 +1083,13 @@ struct osi_setup_entry { bool enable; }; -static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX]; +static struct osi_setup_entry __initdata + osi_setup_entries[OSI_STRING_ENTRIES_MAX] = { + {"Module Device", true}, + {"Processor Device", true}, + {"3.0 _SCP Extensions", true}, + {"Processor Aggregator Device", true}, +}; void __init acpi_osi_setup(char *str) { -- cgit v0.10.2 From 6c8111e9a0e73ef1e58a1bf0a10c23ee1512e7a2 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 2 Aug 2011 17:15:33 -0400 Subject: ACPI: delete stale reference in kernel-parameters.txt Says for acpi= See also Documentation/power/pm.txt, pci=noacpi but this file does not exist Reported-by: Alan Cox Signed-off-by: Len Brown diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index aa47be7..53800c2 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -161,8 +161,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory - See also Documentation/power/pm.txt, pci=noacpi - acpi_apic_instance= [ACPI, IOAPIC] Format: 2: use 2nd APIC table, if available -- cgit v0.10.2