From 7292576043666ff39946dee14641fe719ba8c7e8 Mon Sep 17 00:00:00 2001 From: Konstantin Karasyov Date: Wed, 21 Feb 2007 02:05:58 -0500 Subject: ACPI: fix S3 fan resume issue http://bugzilla.kernel.org/show_bug.cgi?id=7570#c14 Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown --- drivers/acpi/power.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1ef338545df..547eee7537b 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state) cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; - device->power.state = ACPI_STATE_UNKNOWN; - if (!cl->count && !tl->count) { result = -ENODEV; goto end; @@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state) goto end; } - /* We shouldn't change the state till all above operations succeed */ - device->power.state = state; - end: - if (result) + end: + if (result) { + device->power.state = ACPI_STATE_UNKNOWN; printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", device->pnp.bus_id, state); + } else { + /* We shouldn't change the state till all above operations succeed */ + device->power.state = state; + } return result; } -- cgit v1.2.3-70-g09d2 From adb005818b71e9476581a1de5742e2f427ac9e2b Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 22 Feb 2007 16:04:55 -0200 Subject: ACPI: ibm-acpi: fix initial status of backlight device The brightness class core does not update the initial status of the device's brightness at register time. Do it by ourselves. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Richard Purdie --- drivers/acpi/ibm_acpi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 4cc534e36e8..7c1b418676b 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1711,6 +1711,12 @@ static struct backlight_ops ibm_backlight_data = { static int brightness_init(void) { + int b; + + b = brightness_get(NULL); + if (b < 0) + return b; + ibm_backlight_device = backlight_device_register("ibm", NULL, NULL, &ibm_backlight_data); if (IS_ERR(ibm_backlight_device)) { @@ -1718,7 +1724,9 @@ static int brightness_init(void) return PTR_ERR(ibm_backlight_device); } - ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.brightness = b; + backlight_update_status(ibm_backlight_device); return 0; } -- cgit v1.2.3-70-g09d2 From 2bc808a8c4821a8ef4e3dc35b8fc577a9d2c6f0d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Wed, 21 Feb 2007 13:05:38 -0200 Subject: ACPI: ibm-acpi: make ibm-acpi bay support optional Make ibm-acpi bay support optional at kernel compile time. Signed-off-by: Henrique de Moraes Holschuh --- drivers/acpi/Kconfig | 11 +++++++++++ drivers/acpi/ibm_acpi.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index e942ffe8b57..ee3dcd12182 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -242,6 +242,17 @@ config ACPI_IBM_DOCK If you are not sure, say N here. +config ACPI_IBM_BAY + bool "Legacy Removable Bay Support" + depends on ACPI_IBM + default y + ---help--- + Allows the ibm_acpi driver to handle removable bays. It will allow + disabling the device in the bay, and also generate notifications when + the bay lever is ejected or inserted. + + If you are not sure, say Y here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 7c1b418676b..e7309a66873 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -157,6 +157,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ #endif +#ifdef CONFIG_ACPI_IBM_BAY IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ @@ -174,6 +175,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ "_EJ0", /* 770x */ ); /* all others */ +#endif /* CONFIG_ACPI_IBM_BAY */ /* don't list other alternatives as we install a notify handler on the 570 */ IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ @@ -1044,6 +1046,7 @@ static int light_write(char *buf) return 0; } +#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY) static int _sta(acpi_handle handle) { int status; @@ -1053,6 +1056,7 @@ static int _sta(acpi_handle handle) return status; } +#endif #ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) @@ -1119,6 +1123,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) } #endif +#ifdef CONFIG_ACPI_IBM_BAY static int bay_status_supported; static int bay_status2_supported; static int bay_eject_supported; @@ -1194,6 +1199,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event) { acpi_bus_generate_event(ibm->device, event, 0); } +#endif /* CONFIG_ACPI_IBM_BAY */ static int cmos_read(char *p) { @@ -2361,6 +2367,7 @@ static struct ibm_struct ibms[] = { .type = ACPI_SYSTEM_NOTIFY, }, #endif +#ifdef CONFIG_ACPI_IBM_BAY { .name = "bay", .init = bay_init, @@ -2370,6 +2377,7 @@ static struct ibm_struct ibms[] = { .handle = &bay_handle, .type = ACPI_SYSTEM_NOTIFY, }, +#endif /* CONFIG_ACPI_IBM_BAY */ { .name = "cmos", .read = cmos_read, @@ -2655,7 +2663,9 @@ IBM_PARAM(light); #ifdef CONFIG_ACPI_IBM_DOCK IBM_PARAM(dock); #endif +#ifdef CONFIG_ACPI_IBM_BAY IBM_PARAM(bay); +#endif /* CONFIG_ACPI_IBM_BAY */ IBM_PARAM(cmos); IBM_PARAM(led); IBM_PARAM(beep); @@ -2731,12 +2741,14 @@ static int __init acpi_ibm_init(void) IBM_HANDLE_INIT(dock); #endif IBM_HANDLE_INIT(pci); +#ifdef CONFIG_ACPI_IBM_BAY IBM_HANDLE_INIT(bay); if (bay_handle) IBM_HANDLE_INIT(bay_ej); IBM_HANDLE_INIT(bay2); if (bay2_handle) IBM_HANDLE_INIT(bay2_ej); +#endif /* CONFIG_ACPI_IBM_BAY */ IBM_HANDLE_INIT(beep); IBM_HANDLE_INIT(ecrd); IBM_HANDLE_INIT(ecwr); -- cgit v1.2.3-70-g09d2 From 610a3d069665ba2b27e42c90129ce640c4d6e515 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 7 Mar 2007 00:57:30 -0500 Subject: ACPICA: Fix ACPI Global Lock re-entrancy patch "Delete recursive feature of ACPI Global Lock" broke re-entrancy of the Global Lock. The common routine to acquire GL is acpi_ev_acquire_global_lock, so check for re-entrancy _must_ be there, and not anywhere else. http://bugzilla.kernel.org/show_bug.cgi?id=8066#c9 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index d572700197f..8dcade63b04 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -423,6 +423,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void) * the global lock appear as a standard mutex on the OS side. * *****************************************************************************/ +static acpi_thread_id acpi_ev_global_lock_thread_id; +static int acpi_ev_global_lock_acquired; acpi_status acpi_ev_acquire_global_lock(u16 timeout) { @@ -435,11 +437,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Only one thread can acquire the GL at a time, the global_lock_mutex * enforces this. This interface releases the interpreter if we must wait. */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); + if (status == AE_TIME) { + if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { + acpi_ev_global_lock_acquired++; + return AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); + acpi_ev_global_lock_acquired++; + /* * Make sure that a global lock actually exists. If not, just treat * the lock as a standard mutex. @@ -506,6 +521,11 @@ acpi_status acpi_ev_release_global_lock(void) return_ACPI_STATUS(AE_NOT_ACQUIRED); } + acpi_ev_global_lock_acquired--; + if (acpi_ev_global_lock_acquired > 0) { + return AE_OK; + } + if (acpi_gbl_global_lock_present) { /* Allow any thread to release the lock */ @@ -529,7 +549,8 @@ acpi_status acpi_ev_release_global_lock(void) acpi_gbl_global_lock_acquired = FALSE; /* Release the local GL mutex */ - + acpi_ev_global_lock_thread_id = 0; + acpi_ev_global_lock_acquired = 0; acpi_os_release_mutex(acpi_gbl_global_lock_mutex); return_ACPI_STATUS(status); } -- cgit v1.2.3-70-g09d2 From ff24ba74b6d3befbfbafa142582211b5a6095d45 Mon Sep 17 00:00:00 2001 From: Konstantin Karasyov Date: Wed, 7 Mar 2007 03:50:11 -0500 Subject: ACPI: ThinkPad Z60m: usb mouse stops working after suspend to RAM (http://www.mail-archive.com/linux-acpi@vger.kernel.org/msg05270.html): References : http://lkml.org/lkml/2007/2/21/413 http://lkml.org/lkml/2007/2/28/172 Submitter : Arkadiusz Miskiewicz Caused-By : Konstantin Karasyov commit 0a6139027f3986162233adc17285151e78b39cac Do not disable power resources on resume even if there are no devices referencing it. Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown --- drivers/acpi/power.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1ef338545df..ccecfe0d695 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -687,13 +687,6 @@ static int acpi_power_resume(struct acpi_device *device) return result; mutex_lock(&resource->resource_lock); - if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) && - list_empty(&resource->reference)) { - mutex_unlock(&resource->resource_lock); - result = acpi_power_off_device(device->handle, NULL); - return result; - } - if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && !list_empty(&resource->reference)) { ref = container_of(resource->reference.next, struct acpi_power_reference, node); -- cgit v1.2.3-70-g09d2 From 2f894ef9c8b36a35d80709bedca276d2fc691941 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 8 Mar 2007 03:42:42 -0500 Subject: ACPI: fix boot hang w/o "noapic" on MSI MS-6390-L This is a workaround to handle a BIOS bug where the programmer exchanged the name and index fields of a _PRT entry. Apparently this BIOS error does not confuse Windows and thus it lurks in the field on various machines. boot with "acpi=strict" to disable this workaround http://bugzilla.kernel.org/show_bug.cgi?id=6859 Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/resources/rscreate.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 1358c06a969..cc48ab05676 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); for (index = 0; index < number_of_elements; index++) { + int source_name_index = 2; + int source_index_index = 3; + /* * Point user_prt past this current structure * @@ -260,11 +263,29 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, return_ACPI_STATUS(AE_BAD_DATA); } + /* + * If BIOS erroneously reversed the _PRT source_name and source_index, + * then reverse them back. + */ + if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) { + if (acpi_gbl_enable_interpreter_slack) { + source_name_index = 3; + source_index_index = 2; + printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n"); + } else { + ACPI_ERROR((AE_INFO, + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(sub_object_list[3]))); + return_ACPI_STATUS(AE_BAD_DATA); + } + } + /* * 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object */ - obj_desc = sub_object_list[2]; + obj_desc = sub_object_list[source_name_index]; if (obj_desc) { switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: @@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ - obj_desc = sub_object_list[3]; + obj_desc = sub_object_list[source_index_index]; if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { user_prt->source_index = (u32) obj_desc->integer.value; } else { -- cgit v1.2.3-70-g09d2 From c9bf296b6467968ecb9d988e7ed754a19c2e63d9 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 8 Mar 2007 05:28:15 -0300 Subject: ACPI: ibm-acpi: improve backlight power handling Improve the backlight code to emulate as much as possible the power management events, as we are unable to really power on or power off the backlight. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Richard Purdie Signed-off-by: Len Brown --- drivers/acpi/ibm_acpi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index e7309a66873..36901362fd2 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -86,6 +86,7 @@ #include #include +#include #include #include @@ -1707,7 +1708,10 @@ static int brightness_write(char *buf) static int brightness_update_status(struct backlight_device *bd) { - return brightness_set(bd->props.brightness); + return brightness_set( + (bd->props.fb_blank == FB_BLANK_UNBLANK && + bd->props.power == FB_BLANK_UNBLANK) ? + bd->props.brightness : 0); } static struct backlight_ops ibm_backlight_data = { -- cgit v1.2.3-70-g09d2 From 5b27b176da6cc83b0f904c7e0aabd9362d70bf70 Mon Sep 17 00:00:00 2001 From: "Anthony Godshall, Ampro Computers, Inc" Date: Fri, 9 Mar 2007 21:19:05 -0500 Subject: ACPI: make blacklist more verbose IMHO, ACPI disabled due to DMI failure or blacklisted year should be noted, as is done with other ACPI blacklisting. This will help people troubleshoot when ACPI isn't working. Status quo is a mysterious "ACPI Disabled" message without explanation on BIOS that implements ACPI but not DMI. This is actually fairly common on embedded x86 boards. Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index f289fd41e77..3ec110ce00c 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -79,11 +79,17 @@ static int __init blacklist_by_year(void) { int year = dmi_get_year(DMI_BIOS_DATE); /* Doesn't exist? Likely an old system */ - if (year == -1) + if (year == -1) { + 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) + 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", -- cgit v1.2.3-70-g09d2 From 98fb8fe10f4b88170f578d8c33eaa2315d73b4f7 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Tue, 20 Feb 2007 16:38:40 +0100 Subject: ACPI: video: Fix spelling and grammar mistakes Correct some of the most obvious spelling and grammar mistakes in drivers/acpi/video.c (comments and printk output). Signed-off-by: Julius Volz Signed-off-by: Len Brown --- drivers/acpi/video.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 0771b434feb..00d25b34725 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -102,9 +102,9 @@ struct acpi_video_bus_cap { struct acpi_video_device_attrib { u32 display_index:4; /* A zero-based instance of the Display */ - u32 display_port_attachment:4; /*This field differenates displays type */ + u32 display_port_attachment:4; /*This field differentiates the display type */ u32 display_type:4; /*Describe the specific type in use */ - u32 vendor_specific:4; /*Chipset Vendor Specifi */ + u32 vendor_specific:4; /*Chipset Vendor Specific */ u32 bios_can_detect:1; /*BIOS can detect the device */ u32 depend_on_vga:1; /*Non-VGA output device whose power is related to the VGA device. */ @@ -484,16 +484,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video, * 0. The system BIOS should NOT automatically switch(toggle) * the active display output. * 1. The system BIOS should automatically switch (toggle) the - * active display output. No swich event. + * active display output. No switch event. * 2. The _DGS value should be locked. * 3. The system BIOS should not automatically switch (toggle) the * active display output, but instead generate the display switch * event notify code. * lcd_flag : * 0. The system BIOS should automatically control the brightness level - * of the LCD, when the power changes from AC to DC + * of the LCD when the power changes from AC to DC * 1. The system BIOS should NOT automatically control the brightness - * level of the LCD, when the power changes from AC to DC. + * level of the LCD when the power changes from AC to DC. * Return Value: * -1 wrong arg. */ @@ -525,7 +525,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) * Return Value: * None * - * Find out all required AML method defined under the output + * Find out all required AML methods defined under the output * device. */ @@ -636,7 +636,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) * Return Value: * None * - * Find out all required AML method defined under the video bus device. + * Find out all required AML methods defined under the video bus device. */ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) @@ -681,19 +681,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video) * to check well known required nodes. */ - /* Does this device able to support video switching ? */ + /* Does this device support video switching? */ if (video->cap._DOS) { video->flags.multihead = 1; status = 0; } - /* Does this device able to retrieve a retrieve a video ROM ? */ + /* Does this device support retrieving a video ROM? */ if (video->cap._ROM) { video->flags.rom = 1; status = 0; } - /* Does this device able to configure which video device to POST ? */ + /* Does this device support configuring which video device to POST? */ if (video->cap._GPD && video->cap._SPD && video->cap._VPO) { video->flags.post = 1; status = 0; @@ -860,7 +860,7 @@ acpi_video_device_write_brightness(struct file *file, if (level > 100) return -EFAULT; - /* validate though the list of available levels */ + /* validate through the list of available levels */ for (i = 0; i < dev->brightness->count; i++) if (level == dev->brightness->levels[i]) { if (ACPI_SUCCESS @@ -1065,10 +1065,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n"); printk(KERN_WARNING PREFIX - "This indicate a BIOS bug. Please contact the manufacturer.\n"); + "This indicates a BIOS bug. Please contact the manufacturer.\n"); } printk("%lx\n", options); - seq_printf(seq, "can POST: "); + seq_printf(seq, "can POST: "); if (options & 2) seq_printf(seq, " "); if (options & 4) @@ -1102,7 +1102,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "\n"); goto end; } - seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]); + seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]); end: return 0; @@ -1156,7 +1156,7 @@ acpi_video_bus_write_POST(struct file *file, if (opt > 3) return -EFAULT; - /* just in case an OEM 'forget' the motherboard... */ + /* just in case an OEM 'forgot' the motherboard... */ options |= 1; if (options & (1ul << opt)) { @@ -1527,13 +1527,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) /* * Arg: * video : video bus device - * event : Nontify Event + * event : notify event * * Return: * < 0 : error * * 1. Find out the current active output device. - * 2. Identify the next output device to switch + * 2. Identify the next output device to switch to. * 3. call _DSS to do actual switch. */ @@ -1723,12 +1723,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) device = video->device; switch (event) { - case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur, + case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, * most likely via hotkey. */ acpi_bus_generate_event(device, event, 0); break; - case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video + case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video * connector. */ acpi_video_device_enumerate(video); acpi_video_device_rebind(video); -- cgit v1.2.3-70-g09d2 From 9327f46ee28116b17f15f6505edd90f905908d62 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sun, 4 Mar 2007 13:17:43 -0500 Subject: ACPI: Kconfig: hide ACPI menu when CONFIG_PM=n Signed-off-by: Robert P. J. Day Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7c49e103cf8..3208ce08d66 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -7,6 +7,7 @@ menu "ACPI (Advanced Configuration and Power Interface) Support" depends on !X86_VISWS depends on !IA64_HP_SIM depends on IA64 || X86 + depends on PM config ACPI bool "ACPI Support" -- cgit v1.2.3-70-g09d2 From 9e197219605513c14d3eae41039ecf1b82d1920d Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 7 Mar 2007 18:29:35 -0500 Subject: ACPI: ec: fix race in status register access Delay the read of the EC status register until after the event that caused it occurs -- otherwise it is possible to read and act on stale status that was associated with the previous event. Do this with a perpetually incrementing "event_count" to detect when a new event occurs and it is safe to read status. There is no workaround for polling mode -- it is inherently exposed to reading and acting on stale status, since it doesn't have an interrupt to tell it the event completed. http://bugzilla.kernel.org/show_bug.cgi?id=8110 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ab688837379..a802962ff2b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -100,6 +100,7 @@ static struct acpi_ec { unsigned long global_lock; struct mutex lock; atomic_t query_pending; + atomic_t event_count; atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ wait_queue_head_t wait; } *ec_ecdt; @@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) +static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, + unsigned old_count) { u8 status = acpi_ec_read_status(ec); - + if (old_count == atomic_read(&ec->event_count)) + return 0; if (event == ACPI_EC_EVENT_OBF_1) { if (status & ACPI_EC_FLAG_OBF) return 1; @@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) { if (acpi_ec_mode == EC_POLL) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event)) + if (acpi_ec_check_status(ec, event, 0)) return 0; } } else { if (wait_event_timeout(ec->wait, - acpi_ec_check_status(ec, event), + acpi_ec_check_status(ec, event, count), msecs_to_jiffies(ACPI_EC_DELAY)) || - acpi_ec_check_status(ec, event)) { + acpi_ec_check_status(ec, event, 0)) { return 0; } else { printk(KERN_ERR PREFIX "acpi_ec_wait timeout," @@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, u8 * rdata, unsigned rdata_len) { int result = 0; - + unsigned count = atomic_read(&ec->event_count); acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", command); goto end; } + count = atomic_read(&ec->event_count); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", command); @@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); goto end; } - + count = atomic_read(&ec->event_count); *(rdata++) = acpi_ec_read_data(ec); } end: @@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, /* Make sure GPE is enabled before doing transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_DEBUG PREFIX "input buffer is not empty, aborting transaction\n"); @@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val) EXPORT_SYMBOL(ec_write); int ec_transaction(u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len) + const u8 * wdata, unsigned wdata_len, + u8 * rdata, unsigned rdata_len) { struct acpi_ec *ec; @@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; u8 value; struct acpi_ec *ec = (struct acpi_ec *)data; - + atomic_inc(&ec->event_count); if (acpi_ec_mode == EC_INTR) { wake_up(&ec->wait); } @@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device) ec->uid = -1; mutex_init(&ec->lock); atomic_set(&ec->query_pending, 0); + atomic_set(&ec->event_count, 1); if (acpi_ec_mode == EC_INTR) { atomic_set(&ec->leaving_burst, 1); init_waitqueue_head(&ec->wait); @@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle, acpi_status status; mutex_init(&ec_ecdt->lock); + atomic_set(&ec_ecdt->event_count, 1); if (acpi_ec_mode == EC_INTR) { init_waitqueue_head(&ec_ecdt->wait); } @@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void) return -ENOMEM; mutex_init(&ec_ecdt->lock); + atomic_set(&ec_ecdt->event_count, 1); if (acpi_ec_mode == EC_INTR) { init_waitqueue_head(&ec_ecdt->wait); } @@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str) acpi_ec_mode = EC_POLL; } acpi_ec_driver.ops.add = acpi_ec_add; - printk(KERN_NOTICE PREFIX "%s mode.\n", - intr ? "interrupt" : "polling"); + printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); return 1; } -- cgit v1.2.3-70-g09d2 From a1fdcc0d2714b6622e3fd5c00db1635213d6c41a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 11 Mar 2007 03:26:14 -0400 Subject: ACPI: Add support to parse 2nd MADT When a BIOS bug presents multiple APIC/MADTs, Linux currently uses the 1st and ignores the 2nd. But some machines work better if we use the 2nd. http://bugzilla.kernel.org/show_bug.cgi?id=7465 Add a warning and boot parameter "acpi_apic_instance=2" to allow parsing the 2nd. No change to default behaviour in this patch. Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 6 ++++ drivers/acpi/tables.c | 57 +++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 856c8b114e7..22c6b8ccaea 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -138,6 +138,12 @@ and is between 256 and 4096 characters. It is defined in the file See also Documentation/pm.txt, pci=noacpi + acpi_apic_instance= [ACPI, IOAPIC] + Format: + 2: use 2nd APIC table, if available + 1,0: use 1st APIC table + default: 0 + acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } See Documentation/power/video.txt diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 849e2c36180..c3419182c9a 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,9 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -void acpi_table_print_madt_entry(struct acpi_subtable_header * header) +static int acpi_apic_instance __initdata; + +void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { if (!header) return; @@ -183,8 +185,10 @@ acpi_table_parse_entries(char *id, if (!handler) return -EINVAL; - /* Locate the table (if exists). There should only be one. */ - acpi_get_table(id, 0, &table_header); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table_header); + else + acpi_get_table(id, 0, &table_header); if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); @@ -237,10 +241,15 @@ acpi_table_parse_madt(enum acpi_madt_type id, int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; + if (!handler) return -EINVAL; - acpi_get_table(id, 0, &table); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table); + else + acpi_get_table(id, 0, &table); + if (table) { handler(table); return 0; @@ -248,6 +257,31 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) return 1; } +/* + * The BIOS is supposed to supply a single APIC/MADT, + * but some report two. Provide a knob to use either. + * (don't you wish instance 0 and 1 were not the same?) + */ +static void __init check_multiple_madt(void) +{ + struct acpi_table_header *table = NULL; + + acpi_get_table(ACPI_SIG_MADT, 2, &table); + if (table) { + printk(KERN_WARNING PREFIX + "BIOS bug: multiple APIC/MADT found," + " using %d\n", acpi_apic_instance); + printk(KERN_WARNING PREFIX + "If \"acpi_apic_instance=%d\" works better, " + "notify linux-acpi@vger.kernel.org\n", + acpi_apic_instance ? 0 : 2); + + } else + acpi_apic_instance = 0; + + return; +} + /* * acpi_table_init() * @@ -257,9 +291,22 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) * result: sdt_entry[] is initialized */ - int __init acpi_table_init(void) { acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + check_multiple_madt(); + return 0; +} + +static int __init acpi_parse_apic_instance(char *str) +{ + + acpi_apic_instance = simple_strtoul(str, NULL, 0); + + printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n", + acpi_apic_instance); + return 0; } + +early_param("acpi_apic_instance", acpi_parse_apic_instance); -- cgit v1.2.3-70-g09d2 From 1d99967badac599c0d1db0b45c99e073e8e98cd4 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 12 Mar 2007 14:49:26 -0400 Subject: ACPI: resolve HP nx6125 S3 immediate wakeup regression Moving disable GPEs from enter_sleep up into sleep_prepare fixed the disabled SCI on S4 on Acer laptops. However, it caused an immediate S3 resume on the HP nx6125. Apparently, on the HP, a GPE was getting re-enabled after the prepare, but before the enter. Close that window by restoring the GPE disable on enter. This is redundant in most cases, but closes this window, where S3 and S4 paths differ. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown Acked-by: Ray Lee --- drivers/acpi/hardware/hwsleep.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 8fa93125fd4..c84b1faba28 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -300,6 +300,11 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* * 2) Enable all wakeup GPEs */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes(); -- cgit v1.2.3-70-g09d2 From 89952d133dfbca785ae37b7da13699e4a5e1fa93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 14 Mar 2007 09:17:59 +0000 Subject: [PATCH] misc NULL noise Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/vsyscall.c | 2 +- drivers/acpi/events/evmisc.c | 2 +- drivers/ata/pata_mpc52xx.c | 2 +- drivers/char/watchdog/machzwd.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +++--- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 +++--- drivers/ps3/vuart.c | 4 ++-- drivers/video/backlight/progear_bl.c | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index 180ff919eaf..b43c698cf7d 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -112,7 +112,7 @@ static __always_inline void do_vgettimeofday(struct timeval * tv) vread = __vsyscall_gtod_data.clock.vread; if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) { - gettimeofday(tv,0); + gettimeofday(tv,NULL); return; } now = vread(); diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 8dcade63b04..3a799b9b5df 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -549,7 +549,7 @@ acpi_status acpi_ev_release_global_lock(void) acpi_gbl_global_lock_acquired = FALSE; /* Release the local GL mutex */ - acpi_ev_global_lock_thread_id = 0; + acpi_ev_global_lock_thread_id = NULL; acpi_ev_global_lock_acquired = 0; acpi_os_release_mutex(acpi_gbl_global_lock_mutex); return_ACPI_STATUS(status); diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f5d88729ca7..882c36eaf29 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -329,7 +329,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv) ae->dev = dev; ae->irq = priv->ata_irq; - aio->cmd_addr = 0; /* Don't have a classic reg block */ + aio->cmd_addr = NULL; /* Don't have a classic reg block */ aio->altstatus_addr = &priv->ata_regs->tf_control; aio->ctl_addr = &priv->ata_regs->tf_control; aio->data_addr = &priv->ata_regs->tf_data; diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 4a328ba0d26..81fb3dec180 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -324,7 +324,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(0, p); case WDIOC_KEEPALIVE: - zf_ping(0); + zf_ping(NULL); break; default: diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1ff5138e4bb..9916cf32494 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1248,10 +1248,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_FWPOST1; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { @@ -1320,7 +1320,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 5313d342666..25d3830b482 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -808,11 +808,11 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) { if (vp->dev_video) { pvr2_v4l2_dev_destroy(vp->dev_video); - vp->dev_video = 0; + vp->dev_video = NULL; } if (vp->dev_radio) { pvr2_v4l2_dev_destroy(vp->dev_radio); - vp->dev_radio = 0; + vp->dev_radio = NULL; } pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); @@ -1138,7 +1138,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, { int mindevnum; int unit_number; - int *nr_ptr = 0; + int *nr_ptr = NULL; dip->v4lp = vp; diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c index 1adf186bfaf..6c12744eeb9 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/vuart.c @@ -952,7 +952,7 @@ fail_alloc_irq: kfree(dev->priv); dev->priv = NULL; fail_alloc: - vuart_bus_priv.devices[port_number] = 0; + vuart_bus_priv.devices[port_number] = NULL; fail_match: up(&vuart_bus_priv.probe_mutex); dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); @@ -978,7 +978,7 @@ static int ps3_vuart_remove(struct device *_dev) dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, __LINE__, dev->core.bus_id); - vuart_bus_priv.devices[dev->priv->port_number] = 0; + vuart_bus_priv.devices[dev->priv->port_number] = NULL; if (--vuart_bus_priv.use_count == 0) { BUG(); diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c index 70226935786..836ab4df0ef 100644 --- a/drivers/video/backlight/progear_bl.c +++ b/drivers/video/backlight/progear_bl.c @@ -65,13 +65,13 @@ static int progearbl_probe(struct platform_device *pdev) u8 temp; struct backlight_device *progear_backlight_device; - pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0); + pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!pmu_dev) { printk("ALI M7101 PMU not found.\n"); return -ENODEV; } - sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0); + sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!sb_dev) { printk("ALI 1533 SB not found.\n"); pci_dev_put(pmu_dev); -- cgit v1.2.3-70-g09d2 From a8f4af6dc6600980885c594f52eecd60edd62013 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 15 Mar 2007 04:10:36 -0400 Subject: ACPICA: revert "acpi_serialize" changes This reverts 977a6226feae3e2c10a4d8227625ff0f04b49239 and reverts 1ba753acb372c2955a4843302e92e49ce82e2fea and updates acpi_ev_queue_notify_request() to restore the previous implementation of the "acpi_serialize" workaround. http://bugzilla.kernel.org/show_bug.cgi?id=8171 Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 8 ++- drivers/acpi/events/evregion.c | 15 ++++-- drivers/acpi/events/evxface.c | 6 ++- drivers/acpi/executer/excreate.c | 5 +- drivers/acpi/executer/exsystem.c | 30 ++++++++--- drivers/acpi/executer/exutils.c | 104 ++++++++------------------------------ drivers/acpi/namespace/nseval.c | 11 +++- drivers/acpi/namespace/nsinit.c | 7 ++- drivers/acpi/namespace/nsxfeval.c | 11 ++-- include/acpi/acinterp.h | 6 +-- 10 files changed, 90 insertions(+), 113 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 3a799b9b5df..cae786ca860 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -196,11 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_ev_notify_dispatch(notify_info); - acpi_ex_reacquire_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } if (!handler_obj) { diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index e99f0c435a4..96b0e843174 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 bit_width, acpi_integer * value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; @@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } /* Check for failure of the Region Setup */ @@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 685a103a358..a3379bafa67 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -768,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_ex_enter_interpreter(); status = acpi_ev_acquire_global_lock(timeout); acpi_ex_exit_interpreter(); diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 7c38528a7e8..ae97812681a 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -583,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start, * Get the sync_level. If method is serialized, a mutex will be * created for this method when it is parsed. */ - if (method_flags & AML_METHOD_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.sync_level = 0; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: sync_level = 0 * ACPI 2.0: sync_level = sync_level in method declaration diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baff303..b2edf620ba8 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem") acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); @@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_mutex); @@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { + acpi_status status; + ACPI_FUNCTION_ENTRY(); /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_os_sleep(how_long); /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); - return (AE_OK); + status = acpi_ex_enter_interpreter(); + return (status); } /******************************************************************************* diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69..aea461f3a48 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ -void acpi_ex_enter_interpreter(void) +acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; @@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void) * * RETURN: None * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void) * * RETURN: none * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. * ******************************************************************************/ diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index aa6370c67ec..26fd0dd6953 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); } else { @@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Function has a strange interface */ diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 33db2241044..c4ab615f77f 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; - acpi_status status = AE_OK; + acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = @@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, /* * Must lock the interpreter before executing AML code */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } /* * Each of these types can contain executable AML code within the diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 7ac6ace5005..8904d0fae6a 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -170,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle, struct acpi_buffer *return_buffer) { acpi_status status; + acpi_status status2; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; @@ -328,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle, * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ - acpi_ex_enter_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_SUCCESS(status2)) { - /* Remove one reference on the return object (should delete it) */ + /* Remove one reference on the return object (should delete it) */ - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } } cleanup: diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index 73967c8152d..44098301999 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -446,14 +446,10 @@ acpi_ex_copy_integer_to_buffer_field(union acpi_operand_object *source_desc, /* * exutils - interpreter/scanner utilities */ -void acpi_ex_enter_interpreter(void); +acpi_status acpi_ex_enter_interpreter(void); void acpi_ex_exit_interpreter(void); -void acpi_ex_reacquire_interpreter(void); - -void acpi_ex_relinquish_interpreter(void); - void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); u8 acpi_ex_acquire_global_lock(u32 rule); -- cgit v1.2.3-70-g09d2 From 09fe58356d148ff66901ddf639e725ca1a48a0af Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 11 Mar 2007 03:32:00 -0400 Subject: ACPI: parse 2nd MADT by default http://bugzilla.kernel.org/show_bug.cgi?id=7465 Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 2 +- drivers/acpi/tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 22c6b8ccaea..f0b7a5e5740 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -142,7 +142,7 @@ and is between 256 and 4096 characters. It is defined in the file Format: 2: use 2nd APIC table, if available 1,0: use 1st APIC table - default: 0 + default: 2 acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index c3419182c9a..96792a6cc16 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,7 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -static int acpi_apic_instance __initdata; +static int acpi_apic_instance __initdata = 2; void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { -- cgit v1.2.3-70-g09d2 From 96e89afe6da630dc54cfbca33c2c6a7ab9b6c11b Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 15 Mar 2007 16:15:06 -0300 Subject: ACPI: ibm-acpi: allow module to load when acpi notifiers can't be set (v2) This patch allows for ibm-acpi to coexist (with diminished functionality) with other drivers like ACPI_BAY. ibm-acpi will simply disable the functions it is not able to register ACPI notifiers for. Signed-off-by: Henrique de Moraes Holschuh Cc: Chris Wedgwood Cc: Kristen Carlson Accardi Signed-off-by: Len Brown --- drivers/acpi/ibm_acpi.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 36901362fd2..dc1096608f4 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -2507,7 +2507,7 @@ static int __init setup_notify(struct ibm_struct *ibm) ret = acpi_bus_get_device(*ibm->handle, &ibm->device); if (ret < 0) { printk(IBM_ERR "%s device not present\n", ibm->name); - return 0; + return -ENODEV; } acpi_driver_data(ibm->device) = ibm; @@ -2516,8 +2516,13 @@ static int __init setup_notify(struct ibm_struct *ibm) status = acpi_install_notify_handler(*ibm->handle, ibm->type, dispatch_notify, ibm); if (ACPI_FAILURE(status)) { - printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n", - ibm->name, status); + if (status == AE_ALREADY_EXISTS) { + printk(IBM_NOTICE "another device driver is already handling %s events\n", + ibm->name); + } else { + printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n", + ibm->name, status); + } return -ENODEV; } ibm->notify_installed = 1; @@ -2553,6 +2558,8 @@ static int __init register_driver(struct ibm_struct *ibm) return ret; } +static void ibm_exit(struct ibm_struct *ibm); + static int __init ibm_init(struct ibm_struct *ibm) { int ret; @@ -2594,6 +2601,12 @@ static int __init ibm_init(struct ibm_struct *ibm) if (ibm->notify) { ret = setup_notify(ibm); + if (ret == -ENODEV) { + printk(IBM_NOTICE "disabling subdriver %s\n", + ibm->name); + ibm_exit(ibm); + return 0; + } if (ret < 0) return ret; } -- cgit v1.2.3-70-g09d2 From 25496caec111481161e7f06bbfa12a533c43cc6f Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Tue, 27 Feb 2007 12:13:00 -0500 Subject: ACPI: Only use IPI on known broken machines (AMD, Dothan/BaniasPentium M) Use IPI for blacklisted CPUs, add parameter IPI vs LAPIC Currently, Linux disables lapic timer for all machines with C2 and higher C-state support. According to Intel only specific Intel models (Banias/Dothan) are broken in respect of not waking up from C2 with lapic. However, I am not sure about the naming of the parameter and how it could/should get integrated into the dyntick part (CONFIG_GENERIC_CLOCKEVENTS). There, a more fine grained check (TSC still running?, ..) is needed? Does this make sense (always use CLOCK_EVT_NOTIFY_BROADCAST_ON, but use OFF if forced by use_ipi=0: clockevents_notify(use_ipi ? CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF, &pr->id); Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 60773005b8a..562124ed785 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -89,6 +89,12 @@ module_param(nocst, uint, 0000); static unsigned int bm_history __read_mostly = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); module_param(bm_history, uint, 0644); + +static unsigned use_ipi = 2; +module_param(use_ipi, uint, 0644); +MODULE_PARM_DESC(use_ipi, "IPI (vs. LAPIC) irqs for not waking up from C2/C3" + " machines. 0=apic, 1=ipi, 2=auto\n"); + /* -------------------------------------------------------------------------- Power Management -------------------------------------------------------------------------- */ @@ -260,9 +266,8 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) /* * Some BIOS implementations switch to C3 in the published C2 state. - * This seems to be a common problem on AMD boxen, but other vendors - * are affected too. We pick the most conservative approach: we assume - * that the local APIC stops in both C2 and C3. + * This seems to be a common problem on AMD boxen and Intel Dothan/Banias + * Pentium M machines. */ static void acpi_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx) @@ -276,8 +281,17 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, if (pwr->timer_broadcast_on_state < state) return; - if (cx->type >= ACPI_STATE_C2) - pr->power.timer_broadcast_on_state = state; + if (cx->type >= ACPI_STATE_C2) { + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + pr->power.timer_broadcast_on_state = state; + else if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6) && + (boot_cpu_data.x86_model == 13 || + boot_cpu_data.x86_model == 9)) + { + pr->power.timer_broadcast_on_state = state; + } + } } static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) @@ -292,10 +306,16 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) #else cpumask_t mask = cpumask_of_cpu(pr->id); - if (pr->power.timer_broadcast_on_state < INT_MAX) + if (use_ipi == 0) on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); - else + else if (use_ipi == 1) on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); + else { + if (pr->power.timer_broadcast_on_state < INT_MAX) + on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); + else + on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); + } #endif } @@ -1013,13 +1033,13 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) case ACPI_STATE_C2: acpi_processor_power_verify_c2(cx); - if (cx->valid) + if (cx->valid && use_ipi != 0 && use_ipi != 1) acpi_timer_check_state(i, pr, cx); break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); - if (cx->valid) + if (cx->valid && use_ipi != 0 && use_ipi != 1) acpi_timer_check_state(i, pr, cx); break; } -- cgit v1.2.3-70-g09d2 From 296d93cd0205433489b0689533426ce0a8cf2dec Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Mar 2007 08:03:47 -0700 Subject: Revert "ACPI: Only use IPI on known broken machines (AMD, Dothan/BaniasPentium M)" This reverts commit 25496caec111481161e7f06bbfa12a533c43cc6f, which broke bootup on at least Ingo's ThinkPad T60. Need to figure out exactly what is wrong before we can re-do the logic. Requested-by: Ingo Molnar Acked-by: Thomas Gleixner Cc: Thomas Renninger Cc: Len Brown Signed-off-by: Linus Torvalds --- drivers/acpi/processor_idle.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 562124ed785..60773005b8a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -89,12 +89,6 @@ module_param(nocst, uint, 0000); static unsigned int bm_history __read_mostly = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); module_param(bm_history, uint, 0644); - -static unsigned use_ipi = 2; -module_param(use_ipi, uint, 0644); -MODULE_PARM_DESC(use_ipi, "IPI (vs. LAPIC) irqs for not waking up from C2/C3" - " machines. 0=apic, 1=ipi, 2=auto\n"); - /* -------------------------------------------------------------------------- Power Management -------------------------------------------------------------------------- */ @@ -266,8 +260,9 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) /* * Some BIOS implementations switch to C3 in the published C2 state. - * This seems to be a common problem on AMD boxen and Intel Dothan/Banias - * Pentium M machines. + * This seems to be a common problem on AMD boxen, but other vendors + * are affected too. We pick the most conservative approach: we assume + * that the local APIC stops in both C2 and C3. */ static void acpi_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx) @@ -281,17 +276,8 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, if (pwr->timer_broadcast_on_state < state) return; - if (cx->type >= ACPI_STATE_C2) { - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) - pr->power.timer_broadcast_on_state = state; - else if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && - boot_cpu_data.x86 == 6) && - (boot_cpu_data.x86_model == 13 || - boot_cpu_data.x86_model == 9)) - { - pr->power.timer_broadcast_on_state = state; - } - } + if (cx->type >= ACPI_STATE_C2) + pr->power.timer_broadcast_on_state = state; } static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) @@ -306,16 +292,10 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) #else cpumask_t mask = cpumask_of_cpu(pr->id); - if (use_ipi == 0) + if (pr->power.timer_broadcast_on_state < INT_MAX) on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); - else if (use_ipi == 1) + else on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); - else { - if (pr->power.timer_broadcast_on_state < INT_MAX) - on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); - else - on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); - } #endif } @@ -1033,13 +1013,13 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) case ACPI_STATE_C2: acpi_processor_power_verify_c2(cx); - if (cx->valid && use_ipi != 0 && use_ipi != 1) + if (cx->valid) acpi_timer_check_state(i, pr, cx); break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); - if (cx->valid && use_ipi != 0 && use_ipi != 1) + if (cx->valid) acpi_timer_check_state(i, pr, cx); break; } -- cgit v1.2.3-70-g09d2 From e585bef815c0315f2730d7bb4e15b82602454efd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 23 Mar 2007 16:08:01 +0100 Subject: [PATCH] i386: add command line option "local_apic_timer_c2_ok" It turned out that it is almost impossible to trust ACPI, BIOS & Co. regarding the C states. This was the reason to switch the local apic timer off in C2 state already. OTOH there are sane and well behaving systems, which get punished by that decision. Allow the user to confirm that the local apic timer is trustworthy in C2 state. This keeps the default behaviour on the safe side. Signed-off-by: Thomas Gleixner Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 3 +++ arch/i386/kernel/apic.c | 10 ++++++++++ drivers/acpi/processor_idle.c | 3 ++- include/asm-i386/apic.h | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e39ab0c99fb..09640a8f7ce 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -780,6 +780,9 @@ and is between 256 and 4096 characters. It is defined in the file lapic [IA-32,APIC] Enable the local APIC even if BIOS disabled it. + lapic_timer_c2_ok [IA-32,APIC] trust the local apic timer in + C2 power state. + lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip Format: addr:,irq: diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 244c3fe9b8c..e88415282a6 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -64,6 +64,9 @@ static int enable_local_apic __initdata = 0; static int local_apic_timer_verify_ok; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int local_apic_timer_disabled; +/* Local APIC timer works in C2 */ +int local_apic_timer_c2_ok; +EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); /* * Debug level, exported for io_apic.c @@ -1232,6 +1235,13 @@ static int __init parse_disable_lapic_timer(char *arg) } early_param("nolapic_timer", parse_disable_lapic_timer); +static int __init parse_lapic_timer_c2_ok(char *arg) +{ + local_apic_timer_c2_ok = 1; + return 0; +} +early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); + static int __init apic_set_verbosity(char *str) { if (strcmp("debug", str) == 0) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 60773005b8a..cdf78943af4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -268,6 +268,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx) { struct acpi_processor_power *pwr = &pr->power; + u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2; /* * Check, if one of the previous states already marked the lapic @@ -276,7 +277,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, if (pwr->timer_broadcast_on_state < state) return; - if (cx->type >= ACPI_STATE_C2) + if (cx->type >= type) pr->power.timer_broadcast_on_state = state; } diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index cc6b1652249..a19810a08ae 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -117,6 +117,7 @@ extern void enable_NMI_through_LVT0 (void * dummy); #define ARCH_APICTIMER_STOPS_ON_C3 1 extern int timer_over_8254; +extern int local_apic_timer_c2_ok; #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } -- cgit v1.2.3-70-g09d2 From 4e381a4f06e3c7b350b55a2636b9d45691780eba Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 30 Mar 2007 14:16:10 -0400 Subject: Revert "ACPI: parse 2nd MADT by default" This reverts commit 09fe58356d148ff66901ddf639e725ca1a48a0af. http://bugzilla.kernel.org/show_bug.cgi?id=8283 Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 2 +- drivers/acpi/tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ef2ffded139..12533a958c5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -142,7 +142,7 @@ and is between 256 and 4096 characters. It is defined in the file Format: 2: use 2nd APIC table, if available 1,0: use 1st APIC table - default: 2 + default: 0 acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 96792a6cc16..c3419182c9a 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,7 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -static int acpi_apic_instance __initdata = 2; +static int acpi_apic_instance __initdata; void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { -- cgit v1.2.3-70-g09d2