From c5279dee26c0e8d7c4200993bfc4b540d2469598 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Nov 2008 17:11:53 -0500 Subject: [PATCH 1/4] ACPI: EC: Add some basic check for ECDT data One more ASUS comes with empty ECDT, add a guard for it... http://bugzilla.kernel.org/show_bug.cgi?id=11880 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index cf41f9fc24a..3ba034fffda 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -977,7 +977,6 @@ static const struct acpi_device_id ec_device_ids[] = { int __init acpi_ec_ecdt_probe(void) { - int ret; acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1005,30 +1004,32 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); - } else { - /* This workaround is needed only on some broken machines, - * which require early EC, but fail to provide ECDT */ - acpi_handle x; - printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); - status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, - boot_ec, NULL); - /* Check that acpi_get_devices actually find something */ - if (ACPI_FAILURE(status) || !boot_ec->handle) - goto error; - /* We really need to limit this workaround, the only ASUS, - * which needs it, has fake EC._INI method, so use it as flag. - * Keep boot_ec struct as it will be needed soon. - */ - if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) - return -ENODEV; + /* Add some basic check against completely broken table */ + if (boot_ec->data_addr != boot_ec->command_addr) + goto install; + /* fall through */ } - - ret = ec_install_handlers(boot_ec); - if (!ret) { + /* This workaround is needed only on some broken machines, + * which require early EC, but fail to provide ECDT */ + acpi_handle x; + printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); + status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, + boot_ec, NULL); + /* Check that acpi_get_devices actually find something */ + if (ACPI_FAILURE(status) || !boot_ec->handle) + goto error; + /* We really need to limit this workaround, the only ASUS, + * which needs it, has fake EC._INI method, so use it as flag. + * Keep boot_ec struct as it will be needed soon. + */ + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) + return -ENODEV; +install: + if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; return 0; } - error: +error: kfree(boot_ec); boot_ec = NULL; return -ENODEV; From 3e54048691bce3f323fd5460695273be379803b9 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sat, 29 Nov 2008 07:21:29 +0100 Subject: [PATCH 2/4] ACPI: EC: fix compilation warning Fix the warning introduced in commit c5279dee26c0e8d7c4200993bfc4b540d2469598, and give the dummy variable a more verbose name. drivers/acpi/ec.c: In function 'acpi_ec_ecdt_probe': drivers/acpi/ec.c:1015: warning: ISO C90 forbids mixed declarations and code Signed-off-by: Hannes Eder Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3ba034fffda..6276e5c0fef 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -979,6 +979,7 @@ int __init acpi_ec_ecdt_probe(void) { acpi_status status; struct acpi_table_ecdt *ecdt_ptr; + acpi_handle dummy; boot_ec = make_acpi_ec(); if (!boot_ec) @@ -1011,7 +1012,6 @@ int __init acpi_ec_ecdt_probe(void) } /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ - acpi_handle x; printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, boot_ec, NULL); @@ -1022,7 +1022,7 @@ int __init acpi_ec_ecdt_probe(void) * which needs it, has fake EC._INI method, so use it as flag. * Keep boot_ec struct as it will be needed soon. */ - if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy))) return -ENODEV; install: if (!ec_install_handlers(boot_ec)) { From 935e5f290ec1eb0f1c15004421f5fd3154380fd5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 11 Dec 2008 16:24:52 -0500 Subject: [PATCH 3/4] ACPI: video: Fix reversed brightness behavior on ThinkPad SL series Section B.6.2 of ACPI 3.0b specification that defines _BCL method doesn't require the brightness levels returned to be sorted. At least ThinkPad SL300 (and probably all IdeaPads) returns the array reversed (i.e. bightest levels have lowest indexes), which causes the brightness management behave in completely reversed manner on these machines (brightness increases when the laptop is idle, while the display dims when used). Sorting the array by brightness level values after reading the list fixes the issue. http://bugzilla.kernel.org/show_bug.cgi?id=12037 Signed-off-by: Zhang Rui Tested-by: Lubomir Rintel Signed-off-by: Len Brown --- drivers/acpi/video.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index baa44192972..38bf8b43fd1 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -625,6 +626,16 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) return status; } +/* + * Simple comparison function used to sort backlight levels. + */ + +static int +acpi_video_cmp_level(const void *a, const void *b) +{ + return *(int *)a - *(int *)b; +} + /* * Arg: * device : video output device (LCD, CRT, ..) @@ -676,6 +687,10 @@ acpi_video_init_brightness(struct acpi_video_device *device) count++; } + /* don't sort the first two brightness levels */ + sort(&br->levels[2], count - 2, sizeof(br->levels[2]), + acpi_video_cmp_level, NULL); + if (count < 2) goto out_free_levels; From 7b37b5fd9ba32c0c5afc3537eed7e7466f2173e2 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 23 Dec 2008 01:47:42 -0500 Subject: [PATCH 4/4] ACPI: disable MPS when NO APIC-table found When ACPI is asked to find an MADT (APIC table) and fails, then ACPI expects to run in PIC mode. However, if an MP Table is was found, IRQs will be registered as if an IOAPIC is being used, even though ACPI is configuring interrupt links links for PIC mode. In this scenario, disable MPS so that IRQs are registered in PIC mode, consistent with ACPI. http://bugzilla.kernel.org/show_bug.cgi?id=12257 Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 4c51a2f8fd3..de8ce79dd88 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1359,6 +1359,17 @@ static void __init acpi_process_madt(void) "Invalid BIOS MADT, disabling ACPI\n"); disable_acpi(); } + } else { + /* + * ACPI found no MADT, and so ACPI wants UP PIC mode. + * In the event an MPS table was found, forget it. + * Boot with "acpi=off" to use MPS on such a system. + */ + if (smp_found_config) { + printk(KERN_WARNING PREFIX + "No APIC-table, disabling MPS\n"); + smp_found_config = 0; + } } #endif return;