From b95e9e8d94484c2823be67416f25e9756db149dc Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 17 Feb 2008 13:22:48 +0100 Subject: ACPI: fix section mismatch in processor_core.c:acpi_processor_hotplug_notify Fix following warning: WARNING: vmlinux.o(.text+0x55586c): Section mismatch in reference from the function acpi_processor_hotplug_notify() to the function .cpuinit.text:acpi_processor_start() acpi_processor_hotplug_notify() may safely reference __cpuinit stuff as it ids defined inside an ACPI_HOTPLUG_CPU block. So annotate it __ref to silence the warning. Signed-off-by: Sam Ravnborg Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 75ccf5d18bf4..d3cc07fa4480 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -881,8 +881,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) return 0; } -static void -acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) +static void __ref acpi_processor_hotplug_notify(acpi_handle handle, + u32 event, void *data) { struct acpi_processor *pr; struct acpi_device *device = NULL; -- cgit From 7560e385651c60e5ffdf07cb94fa7d1658ab0b7a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 17 Feb 2008 13:22:54 +0100 Subject: acer-wmi: fix section mismatch warnings Fix following warnings: WARNING: vmlinux.o(.text+0x672615): Section mismatch in reference from the function acer_platform_remove() to the function .exit.text:acer_backlight_exit() WARNING: vmlinux.o(.devinit.text+0x1e859): Section mismatch in reference from the function acer_platform_probe() to the function .init.text:acer_led_init() WARNING: vmlinux.o(.devinit.text+0x1e878): Section mismatch in reference from the function acer_platform_probe() to the function .init.text:acer_backlight_init() Remove __exit annotation from acer_backlight_exit(). We cannot reference a __exit annotated function from non __exit functions. acer_led_init() and acer_backlight_init() where both annotated __init but used from a __devinit function. This would result in an oops should gcc drop their inlining and the module are hot plugged. Fix by annotating acer_led_init() and acer_backlight_init() __devinit. Signed-off-by: Sam Ravnborg Cc: Carlos Corbacho Signed-off-by: Len Brown --- drivers/misc/acer-wmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index d7aea93081f2..cdc733b77fe3 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -756,7 +756,7 @@ static struct led_classdev mail_led = { .brightness_set = mail_led_set, }; -static int __init acer_led_init(struct device *dev) +static int __devinit acer_led_init(struct device *dev) { return led_classdev_register(dev, &mail_led); } @@ -789,7 +789,7 @@ static struct backlight_ops acer_bl_ops = { .update_status = update_bl_status, }; -static int __init acer_backlight_init(struct device *dev) +static int __devinit acer_backlight_init(struct device *dev) { struct backlight_device *bd; @@ -808,7 +808,7 @@ static int __init acer_backlight_init(struct device *dev) return 0; } -static void __exit acer_backlight_exit(void) +static void acer_backlight_exit(void) { backlight_device_unregister(acer_backlight_device); } -- cgit From b5678a34762edf2c8de1c60c125fea42a8c17e63 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 17 Feb 2008 13:23:03 +0100 Subject: ACPI: fix section mismatch in acpi_pci_root_add Fix following warning: WARNING: vmlinux.o(.text+0x550e85): Section mismatch in reference from the function acpi_pci_root_add() to the function .devinit.text:pci_acpi_scan_root() acpi_pci_root_add uses a __devinit annotated function and it looks like annotating it __devinit too is the correct fix. Signed-off-by: Sam Ravnborg Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index f14ff1ffab29..c3fed31166b5 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -184,7 +184,7 @@ static void acpi_pci_bridge_scan(struct acpi_device *device) } } -static int acpi_pci_root_add(struct acpi_device *device) +static int __devinit acpi_pci_root_add(struct acpi_device *device) { int result = 0; struct acpi_pci_root *root = NULL; -- cgit From d399d130c82a1e1751b7770944f487fbd8b6272a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 20 Feb 2008 00:59:03 +0200 Subject: sony-laptop.c: fix off-by-one This patch fixes an off-by-one spotted by the Coverity checker. Signed-off-by: Adrian Bunk Acked-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/misc/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 899e3f75f288..02ff3d19b1cc 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -315,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event) break; default: - if (event > ARRAY_SIZE(sony_laptop_input_index)) { + if (event >= ARRAY_SIZE(sony_laptop_input_index)) { dprintk("sony_laptop_report_input_event, event not known: %d\n", event); break; } -- cgit From 3b5fee5952ff7eb6ff7a64247a01040b8b331b74 Mon Sep 17 00:00:00 2001 From: Holger Macht Date: Thu, 14 Feb 2008 13:40:34 +0100 Subject: ACPI: Do not pass NULL to acpi_get_handle() when looking for _EJD When trying to get the acpi_handle from an acpi_buffer, pass ACPI_ROOT_OBJECT instead of NULL to acpi_get_handle(). This fixes the detection of dock dependent bays. Signed-off-by: Holger Macht Tested-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3fac011f9cf9..d9b914303b9c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -609,7 +609,8 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer); if (ACPI_SUCCESS(status)) { obj = buffer.pointer; - status = acpi_get_handle(NULL, obj->string.pointer, ejd); + status = acpi_get_handle(ACPI_ROOT_OBJECT, obj->string.pointer, + ejd); kfree(buffer.pointer); } return status; -- cgit From 7ce9573e093891f5807e6e50f3bd2012f1e5d0fe Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 22 Feb 2008 11:25:04 -0800 Subject: ACPI: prevent randconfig build failure on empty ACPI_CUSTOM_DSDT_FILE Make ACPI_CUSTOM_DSDT boolean config symbol a hidden and derived value, based on the value of ACPI_CUSTOM_DSDT_FILE (string). Only the latter is presented to the user as a config option. This fixes problems with "make randconfig" setting ACPI_CUSTOM_DSDT but leaving ACPI_CUSTOM_DSDT_FILE empty/blank. Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f688c214be0c..fbcaa069be86 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -283,24 +283,23 @@ config ACPI_TOSHIBA If you have a legacy free Toshiba laptop (such as the Libretto L1 series), say Y. -config ACPI_CUSTOM_DSDT - bool "Include Custom DSDT" +config ACPI_CUSTOM_DSDT_FILE + string "Custom DSDT Table file to include" + default "" depends on !STANDALONE - default n help This option supports a custom DSDT by linking it into the kernel. See Documentation/acpi/dsdt-override.txt - If unsure, say N. - -config ACPI_CUSTOM_DSDT_FILE - string "Custom DSDT Table file to include" - depends on ACPI_CUSTOM_DSDT - default "" - help Enter the full path name to the file which includes the AmlCode declaration. + If unsure, don't enter a file name. + +config ACPI_CUSTOM_DSDT + bool + default ACPI_CUSTOM_DSDT_FILE != "" + config ACPI_CUSTOM_DSDT_INITRD bool "Read Custom DSDT from initramfs" depends on BLK_DEV_INITRD -- cgit From 583c377f1d58e705f75d8d5648ab41722be1ebca Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 22 Feb 2008 21:41:51 -0800 Subject: ACPI: acpi_pci_set_power_state() cleanups Minor cleanups to acpi_pci_set_power_state(): use the ACPI and PCI state symbols to make clear that a mapping is being done between PCI and ACPI states, instead of using magic numbers. For paranoia's sake, report any errors. Save five bytes (x86_64) too. Signed-off-by: David Brownell Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 4a23654184fc..72f7476930c8 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -272,21 +272,29 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); acpi_handle tmp; - static int state_conv[] = { - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 3, - [4] = 3 + static const u8 state_conv[] = { + [PCI_D0] = ACPI_STATE_D0, + [PCI_D1] = ACPI_STATE_D1, + [PCI_D2] = ACPI_STATE_D2, + [PCI_D3hot] = ACPI_STATE_D3, + [PCI_D3cold] = ACPI_STATE_D3 }; - int acpi_state = state_conv[(int __force) state]; if (!handle) return -ENODEV; /* If the ACPI device has _EJ0, ignore the device */ if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) return 0; - return acpi_bus_set_power(handle, acpi_state); + + switch (state) { + case PCI_D0: + case PCI_D1: + case PCI_D2: + case PCI_D3hot: + case PCI_D3cold: + return acpi_bus_set_power(handle, state_conv[state]); + } + return -EINVAL; } -- cgit From d0ce46f550ebbd765881e8c48f43b66285d798b0 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 23 Feb 2008 01:53:09 -0500 Subject: ACPI Exception (): AE_NOT_FOUND, Processor Device is not present (update) update cfaf3747ff3d431fba33f75083b7f50f58ae22ff ACPI: ACPI Exception (): AE_NOT_FOUND, Processor Device is not present is_processor_present is only called in the processor hotplug case, and _STA method is mandatory at this time. We should ignore those processors that are disabled in the MADT and don't have _STA methods. Because they will never exist in this system. For the processors that don't physically exist but can be hot plugged later, we still need this debug info. http://bugzilla.kernel.org/show_bug.cgi?id=8570 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a3cc8a98255c..d9316ab66347 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle) status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - /* - * if a processor object does not have an _STA object, - * OSPM assumes that the processor is present. - */ - if (status == AE_NOT_FOUND) - return 1; if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) return 1; - ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); + /* + * _STA is mandatory for a processor that supports hot plug + */ + if (status == AE_NOT_FOUND) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Processor does not support hot plug\n")); + else + ACPI_EXCEPTION((AE_INFO, status, + "Processor Device is not present")); return 0; } -- cgit From c8d16e27a3601d1cbcdfe657eb4ff5e762019e8d Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 29 Feb 2008 07:38:54 +0800 Subject: ACPI: fix boot oops regression in thermal Fix a memory overflow bug when copying NULL internal package element object to external. http://bugzilla.kernel.org/show_bug.cgi?id=10132 Signed-off-by: Lin Ming Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/utilities/utobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 76ee766c84f9..e08b3fa6639f 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * element -- which is legal) */ if (!internal_object) { - *obj_length = 0; + *obj_length = sizeof(union acpi_object); return_ACPI_STATUS(AE_OK); } -- cgit From 4af8e10a6c57e7292862bd1703712f0565c7e429 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 11 Mar 2008 00:27:16 -0400 Subject: Revert "ACPI: EC: Use proper handle for boot EC" This reverts commit 208c70a45624400fafd7511b96bc426bf01f8f5e. http://bugzilla.kernel.org/show_bug.cgi?id=10100 Signed-off-by: Len Brown --- drivers/acpi/ec.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index caf873c14bfb..7222a18a0319 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -943,11 +943,7 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; - if (ACPI_FAILURE(acpi_get_handle(NULL, ecdt_ptr->id, - &boot_ec->handle))) { - pr_info("Failed to locate handle for boot EC\n"); - boot_ec->handle = ACPI_ROOT_OBJECT; - } + boot_ec->handle = ACPI_ROOT_OBJECT; } else { /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ -- cgit From bd12935f04066df31903eaf74b1cec03319ecd2e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 27 Feb 2008 20:56:01 +0100 Subject: ACPI: Fix a duplicate log level Signed-off-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 8edba7b678eb..065819ba87c7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1237,7 +1237,7 @@ int acpi_check_resource_conflict(struct resource *res) if (clash) { if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { - printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]" + printk("%sACPI: %s resource %s [0x%llx-0x%llx]" " conflicts with ACPI region %s" " [0x%llx-0x%llx]\n", acpi_enforce_resources == ENFORCE_RESOURCES_LAX -- cgit From 96b2dd1f1fdb9a131b7f2e79e5c7b2e4282cfcbf Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 5 Mar 2008 18:24:51 -0800 Subject: ACPI: replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Len Brown --- drivers/acpi/bus.c | 2 +- drivers/acpi/scan.c | 2 +- drivers/acpi/sleep/main.c | 2 +- drivers/acpi/utilities/utdebug.c | 2 +- drivers/acpi/video.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ce3c0a2cbac4..5b6760e0f957 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -776,7 +776,7 @@ static int __init acpi_init(void) acpi_kobj = kobject_create_and_add("acpi", firmware_kobj); if (!acpi_kobj) { - printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__); + printk(KERN_WARNING "%s: kset create error\n", __func__); acpi_kobj = NULL; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3fac011f9cf9..b26e3019e1cc 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -966,7 +966,7 @@ static void acpi_device_set_id(struct acpi_device *device, case ACPI_BUS_TYPE_DEVICE: status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__); + printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); return; } diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 293a1cbb47c0..d2f71a54726c 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -504,7 +504,7 @@ static void acpi_power_off_prepare(void) static void acpi_power_off(void) { /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ - printk("%s called\n", __FUNCTION__); + printk("%s called\n", __func__); local_irq_disable(); acpi_enable_wakeup_device(ACPI_STATE_S5); acpi_enter_sleep_state(ACPI_STATE_S5); diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index c7e128e5369b..7361204b1eef 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -109,7 +109,7 @@ void acpi_ut_track_stack_ptr(void) * RETURN: Updated pointer to the function name * * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. - * This allows compiler macros such as __FUNCTION__ to be used + * This allows compiler macros such as __func__ to be used * with no change to the debug output. * ******************************************************************************/ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 12cce69b5441..d64a142e5e10 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1201,7 +1201,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) if (!video) goto end; - printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__); + printk(KERN_INFO PREFIX "Please implement %s\n", __func__); seq_printf(seq, "\n"); end: -- cgit From 2c81ce4c9c37b910210f2640c28e98a0c398dc26 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 11 Mar 2008 13:30:00 -0400 Subject: ACPI: EC: Handle IRQ storm on Acer laptops On some Acer systems, the HW fails to clear the GPE source, causing an interrupt storm. So in EC interrupt mode, we count how many interrupts we receive when waiting. If we get more than 5, we give up on interrupt mode and revert to polling mode. Also, for polling mode to work on Acers, we need to insert a delay. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index caf873c14bfb..2c77359dbdc9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -129,6 +129,7 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; + atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { int ret = 0; + atomic_set(&ec->irq_count, 0); + if (unlikely(event == ACPI_EC_EVENT_OBF_1 && test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) force_poll = 1; @@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) goto end; + msleep(5); } } pr_err(PREFIX "acpi_ec_wait timeout," @@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data) struct acpi_ec *ec = data; pr_debug(PREFIX "~~~> interrupt\n"); + atomic_inc(&ec->irq_count); + if (atomic_read(&ec->irq_count) > 5) { + pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); + acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + return ACPI_INTERRUPT_HANDLED; + } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); -- cgit From 4db42c51ce0033f409fc3a2742e7aa2efa03f7c3 Mon Sep 17 00:00:00 2001 From: "arvidjaar@mail.ru" Date: Tue, 4 Mar 2008 15:06:34 -0800 Subject: toshiba_acpi: Enable autoloading This adds aliases to enable autoloading of toishiba_acpi. Two aliases are defined - TOS6200 (for \\_SB_.VALD.GHCI) and TSO1900 (for \\_SB_.VALZ.GHCI). This allows toishiba_acpi to be autoloaded on systems that provide those devices. Signed-off-by: Andrey Borzenkov Cc: Olivier Blin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/toshiba_acpi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 9e8c20c6a0b7..0a43c8e0eff3 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -99,6 +99,13 @@ MODULE_LICENSE("GPL"); #define HCI_VIDEO_OUT_CRT 0x2 #define HCI_VIDEO_OUT_TV 0x4 +static const struct acpi_device_id toshiba_device_ids[] = { + {"TOS6200", 0}, + {"TOS1900", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); + /* utility */ -- cgit From 3b34e5232fa9776e9a4b3f539cd9fee7609c900e Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Tue, 4 Mar 2008 15:06:35 -0800 Subject: ACPI: button: make real parent for input devices in device tree Signed-off-by: Andrey Borzenkov Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/button.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 24a7865a57cb..6c5da83cdb68 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -449,6 +449,7 @@ static int acpi_button_add(struct acpi_device *device) input->phys = button->phys; input->id.bustype = BUS_HOST; input->id.product = button->type; + input->dev.parent = &device->dev; switch (button->type) { case ACPI_BUTTON_TYPE_POWER: -- cgit From d6f882e10442c1ea6ed5f93365f48be4cb520be7 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Tue, 4 Mar 2008 15:06:36 -0800 Subject: ACPI: use ACPI_DEBUG_PRINT instead of printk in acpi_processor_hotplug_notify() For consistency, use ACPI_DEBUG_PRINT instead of printk in acpi_processor_hotplug_notify() for BUS_CHECK and DEVICE_CHECK events Signed-off-by: Glauber Costa Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a3cc8a98255c..3501cb53857b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -897,9 +897,10 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - printk("Processor driver received %s event\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Processor driver received %s event\n", (event == ACPI_NOTIFY_BUS_CHECK) ? - "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); + "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK")); if (!is_processor_present(handle)) break; -- cgit From 140277e9a710202608914b5b731948d2769399bc Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Fri, 14 Dec 2007 01:53:56 -0800 Subject: IB/ipath: Fix IB compliance problems with link state vs physical state Subnet manager SetPortinfo messages distingush between changing the link state (DOWN, ARM, ACTIVE) and the link physical state (POLL, SLEEP, DISABLED). These are somewhat independent commands and affect when link width and speed changes take effect. Without this patch, a link DOWN physical state NOP command was causing the link width and speed settings to take effect which should only happen when the link physical state is goes down (either by a SMP or some link physical error like link errors exceeding the threshold). Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_common.h | 2 +- drivers/infiniband/hw/ipath/ipath_driver.c | 28 ++++++++++++--------------- drivers/infiniband/hw/ipath/ipath_kernel.h | 1 + drivers/infiniband/hw/ipath/ipath_mad.c | 7 +++---- drivers/infiniband/hw/ipath/ipath_registers.h | 2 +- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h index 414621095540..591901aab6b7 100644 --- a/drivers/infiniband/hw/ipath/ipath_common.h +++ b/drivers/infiniband/hw/ipath/ipath_common.h @@ -75,7 +75,7 @@ #define IPATH_IB_LINKDOWN 0 #define IPATH_IB_LINKARM 1 #define IPATH_IB_LINKACTIVE 2 -#define IPATH_IB_LINKINIT 3 +#define IPATH_IB_LINKDOWN_ONLY 3 #define IPATH_IB_LINKDOWN_SLEEP 4 #define IPATH_IB_LINKDOWN_DISABLE 5 #define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */ diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index d5ff6ca2db30..ca4d0acc6786 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -851,8 +851,7 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, * -ETIMEDOUT state can have multiple states set, for any of several * transitions. */ -static int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, - int msecs) +int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs) { dd->ipath_state_wanted = state; wait_event_interruptible_timeout(ipath_state_wait, @@ -1656,8 +1655,8 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl) static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) { static const char *what[4] = { - [0] = "DOWN", - [INFINIPATH_IBCC_LINKCMD_INIT] = "INIT", + [0] = "NOP", + [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN", [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" }; @@ -1672,9 +1671,9 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) (dd, dd->ipath_kregs->kr_ibcstatus) >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); - /* flush all queued sends when going to DOWN or INIT, to be sure that + /* flush all queued sends when going to DOWN to be sure that * they don't block MAD packets */ - if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) + if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN) ipath_cancel_sends(dd, 1); ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, @@ -1687,6 +1686,13 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) int ret; switch (newstate) { + case IPATH_IB_LINKDOWN_ONLY: + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN << + INFINIPATH_IBCC_LINKCMD_SHIFT); + /* don't wait */ + ret = 0; + goto bail; + case IPATH_IB_LINKDOWN: ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL << INFINIPATH_IBCC_LINKINITCMD_SHIFT); @@ -1709,16 +1715,6 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) ret = 0; goto bail; - case IPATH_IB_LINKINIT: - if (dd->ipath_flags & IPATH_LINKINIT) { - ret = 0; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT << - INFINIPATH_IBCC_LINKCMD_SHIFT); - lstate = IPATH_LINKINIT; - break; - case IPATH_IB_LINKARM: if (dd->ipath_flags & IPATH_LINKARMED) { ret = 0; diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 4cc0f95ea877..ecf3f7ff7717 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -767,6 +767,7 @@ void ipath_kreceive(struct ipath_portdata *); int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned); int ipath_reset_device(int); void ipath_get_faststats(unsigned long); +int ipath_wait_linkstate(struct ipath_devdata *, u32, int); int ipath_set_linkstate(struct ipath_devdata *, u8); int ipath_set_mtu(struct ipath_devdata *, u16); int ipath_set_lid(struct ipath_devdata *, u32, u8); diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index d98d5f103700..b34b91d3723a 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c @@ -555,10 +555,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, /* FALLTHROUGH */ case IB_PORT_DOWN: if (lstate == 0) - if (get_linkdowndefaultstate(dd)) - lstate = IPATH_IB_LINKDOWN_SLEEP; - else - lstate = IPATH_IB_LINKDOWN; + lstate = IPATH_IB_LINKDOWN_ONLY; else if (lstate == 1) lstate = IPATH_IB_LINKDOWN_SLEEP; else if (lstate == 2) @@ -568,6 +565,8 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, else goto err; ipath_set_linkstate(dd, lstate); + ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED | + IPATH_LINKACTIVE, 1000); break; case IB_PORT_ARMED: ipath_set_linkstate(dd, IPATH_IB_LINKARM); diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h index 6d2a17f9c1da..92ad73a7fff0 100644 --- a/drivers/infiniband/hw/ipath/ipath_registers.h +++ b/drivers/infiniband/hw/ipath/ipath_registers.h @@ -185,7 +185,7 @@ #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16 #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL -#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */ +#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */ #define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */ #define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */ #define INFINIPATH_IBCC_LINKCMD_SHIFT 18 -- cgit From 87d5aed85b2d79e4075ad2ca1449e9b98f657a09 Mon Sep 17 00:00:00 2001 From: Patrick Marchand Latifi Date: Mon, 7 Jan 2008 23:43:04 -0800 Subject: IB/ipath: Fix potentially wrong RNR retry counter returned in ipath_query_qp() There can be a case where the requester's rnr retry counter (s_rnr_retry) is less than the number of rnr retries allowed per QP (s_rnr_retry_cnt). This can happen if the s_rnr_retry counter is being decremented and an ipath_query_qp call is issued during that time frame. The fix is to always return the number of rnr retries allowed per QP instead of the requester's rnr counter. Found by code review. Signed-off-by: Patrick Marchand Latifi Acked-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 80dc623cee40..8214c0905c75 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -647,7 +647,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr->port_num = 1; attr->timeout = qp->timeout; attr->retry_cnt = qp->s_retry_cnt; - attr->rnr_retry = qp->s_rnr_retry; + attr->rnr_retry = qp->s_rnr_retry_cnt; attr->alt_port_num = 0; attr->alt_timeout = 0; -- cgit From 4cd5060cf7c2207c31e2e368f8a6343355362e51 Mon Sep 17 00:00:00 2001 From: Patrick Marchand Latifi Date: Fri, 18 Jan 2008 20:10:48 -0800 Subject: IB/ipath: Fix RC QP initialization This patch fixes the initialization of RC QPs, since we would rely on the queue pair type (ibqp->qp_type) being set, but this field is only initialized when we return from ipath_create_qp (it is initialized by the user-level verbs library). The fix is to not depend on this field to initialize the send and the receive state of the RC QP. Signed-off-by: Patrick Marchand Latifi Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_qp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 8214c0905c75..553d9007cf07 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -329,8 +329,9 @@ struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn) /** * ipath_reset_qp - initialize the QP state to the reset state * @qp: the QP to reset + * @type: the QP type */ -static void ipath_reset_qp(struct ipath_qp *qp) +static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) { qp->remote_qpn = 0; qp->qkey = 0; @@ -342,7 +343,7 @@ static void ipath_reset_qp(struct ipath_qp *qp) qp->s_psn = 0; qp->r_psn = 0; qp->r_msn = 0; - if (qp->ibqp.qp_type == IB_QPT_RC) { + if (type == IB_QPT_RC) { qp->s_state = IB_OPCODE_RC_SEND_LAST; qp->r_state = IB_OPCODE_RC_SEND_LAST; } else { @@ -534,7 +535,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, switch (new_state) { case IB_QPS_RESET: - ipath_reset_qp(qp); + ipath_reset_qp(qp, ibqp->qp_type); break; case IB_QPS_ERR: @@ -839,7 +840,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, goto bail_qp; } qp->ip = NULL; - ipath_reset_qp(qp); + ipath_reset_qp(qp, init_attr->qp_type); break; default: -- cgit From 2a049e514b890c8b70b965bbd9f4e3c963af69c9 Mon Sep 17 00:00:00 2001 From: Patrick Marchand Latifi Date: Thu, 31 Jan 2008 00:24:37 -0800 Subject: IB/ipath: Fix error completion put on send CQ instead of recv CQ A work completion entry could be placed on the wrong completion queue when an RC QP is placed in the error state. Signed-off-by: Patrick Marchand Latifi Acked-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 553d9007cf07..087ed3166479 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -415,7 +415,7 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) wc.wr_id = qp->r_wr_id; wc.opcode = IB_WC_RECV; wc.status = err; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1); + ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); } wc.status = IB_WC_WR_FLUSH_ERR; -- cgit From 450bb3875f5f5ab3679823c941d6045d16967370 Mon Sep 17 00:00:00 2001 From: Patrick Marchand Latifi Date: Wed, 20 Feb 2008 19:08:10 -0800 Subject: IB/ipath: Reset the retry counter for RDMA_READ_RESPONSE_MIDDLE packets Reset the retry counter when we get a good RDMA_READ_RESPONSE_MIDDLE packet. This fix will prevent the requester from reporting a retry exceeded error too early. Signed-off-by: Patrick Marchand Latifi --- drivers/infiniband/hw/ipath/ipath_rc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 459e46e2c016..40f3e37d7adc 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -1196,6 +1196,10 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, list_move_tail(&qp->timerwait, &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); + + if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE)) + qp->s_retry = qp->s_retry_cnt; + /* * Update the RDMA receive state but do the copy w/o * holding the locks and blocking interrupts. -- cgit From b3e2749bf32f61e7beb259eb7cfb066d2ec6ad65 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 11 Mar 2008 16:10:02 +0200 Subject: IPoIB: Don't drop multicast sends when they can be queued When set_multicast_list() is called the multicast task is restarted and the IPOIB_MCAST_STARTED bit is cleared. As a result for some window of time, multicast packets are not transmitted nor queued but rather dropped by ipoib_mcast_send(). These dropped packets are painful in two cases: - bonding fail-over which both calls set_multicast_list() on the new active slave and sends Gratuitous ARP through that slave. - IP_DROP_MEMBERSHIP code which both calls set_multicast_list() on the device and issues IGMP leave. In both these cases, depending on the scheduling of the IPoIB multicast task, the packets would be dropped. As a result, in the bonding case, the failover would not be detected by the peers until their neighbour is renewed the neighbour (which takes a few tens of seconds). In the IGMP case, the IP router doesn't get an IGMP leave and would only learn on that from further probes on the group (also a delay of at least a few tens of seconds). Fix this by allowing transmission (or queuing) depending on the IPOIB_FLAG_OPER_UP flag instead of the IPOIB_MCAST_STARTED flag. Signed-off-by: Olga Shern Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 2628339e3a99..31a53c5bcb13 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -650,7 +650,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) */ spin_lock(&priv->lock); - if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) || + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) || !priv->broadcast || !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { ++dev->stats.tx_dropped; -- cgit From 343c00422d3296838927016750b18ead8aa8bf9a Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sun, 24 Feb 2008 13:34:18 +0000 Subject: acer-wmi: Rename mail LED correctly & remove hardcoded colour The mail LED name for acer-wmi currently hardcodes in the colour as green. This is wrong, since many of the newer laptops now come with an orange LED, and we have no way of telling what colour is used on a given system. Also, rename the mail LED to be inline with the current recommendations of the LED class documentation. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- Documentation/laptops/acer-wmi.txt | 2 +- drivers/misc/acer-wmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt index b06696329cff..a346c8666d22 100644 --- a/Documentation/laptops/acer-wmi.txt +++ b/Documentation/laptops/acer-wmi.txt @@ -169,7 +169,7 @@ can be added to acer-wmi. The LED is exposed through the LED subsystem, and can be found in: -/sys/devices/platform/acer-wmi/leds/acer-mail:green/ +/sys/devices/platform/acer-wmi/leds/acer-wmi::mail/ The mail LED is autodetected, so if you don't have one, the LED device won't be registered. diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index 74d12b4a3abd..e85d96f99ae6 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -761,7 +761,7 @@ enum led_brightness value) } static struct led_classdev mail_led = { - .name = "acer-mail:green", + .name = "acer-wmi::mail", .brightness_set = mail_led_set, }; -- cgit From 9b963c40306ba6967650dce99f4e823f1da49a60 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sun, 24 Feb 2008 13:34:29 +0000 Subject: acer-wmi: Don't warn if mail LED cannot be detected This warning confuses users, who think it is an error. Not detecting the mail LED simply means it isn't there, so let's not unduly panic users. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/misc/acer-wmi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index e85d96f99ae6..49846bd2b5c8 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -1069,10 +1069,8 @@ static int __init acer_wmi_init(void) } } - if (wmi_has_guid(AMW0_GUID1)) { - if (ACPI_FAILURE(AMW0_find_mailled())) - printk(ACER_ERR "Unable to detect mail LED\n"); - } + if (wmi_has_guid(AMW0_GUID1)) + AMW0_find_mailled(); find_quirks(); -- cgit From a527f2d7fe58ce95bfec998f3dc6f658c777a2f2 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sun, 24 Feb 2008 13:34:34 +0000 Subject: ACPI: WMI: Clean up handling of spec violating data blocks Acer violate the ACPI-WMI spec by declaring some of their data blocks as expensive, but with no corresponding WCxx method. There is already some workaround code in to handle the initial WCxx call (we just ignore a failure here); but we need to properly check if the second, "clean up", WCxx call is actually needed or not, rather than fail simply because it isn't there. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/acpi/wmi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index efacc9f8bfe3..c33b1c6e93b1 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -293,7 +293,7 @@ struct acpi_buffer *out) { struct guid_block *block = NULL; struct wmi_block *wblock = NULL; - acpi_handle handle; + acpi_handle handle, wc_handle; acpi_status status, wc_status = AE_ERROR; struct acpi_object_list input, wc_input; union acpi_object wc_params[1], wq_params[1]; @@ -338,8 +338,10 @@ struct acpi_buffer *out) * expensive, but have no corresponding WCxx method. So we * should not fail if this happens. */ - wc_status = acpi_evaluate_object(handle, wc_method, - &wc_input, NULL); + wc_status = acpi_get_handle(handle, wc_method, &wc_handle); + if (ACPI_SUCCESS(wc_status)) + wc_status = acpi_evaluate_object(handle, wc_method, + &wc_input, NULL); } strcpy(method, "WQ"); @@ -351,7 +353,7 @@ struct acpi_buffer *out) * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if * the WQxx method failed - we should disable collection anyway. */ - if ((block->flags & ACPI_WMI_EXPENSIVE) && wc_status) { + if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { wc_params[0].integer.value = 0; status = acpi_evaluate_object(handle, wc_method, &wc_input, NULL); -- cgit From 4200406b8fbbf309f4fffb339bd16c4553ae0c30 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 11 Mar 2008 18:35:20 -0700 Subject: IPoIB/cm: Set tx_wr.num_sge in connected mode post_send() Commit 7143740d ("IPoIB: Add send gather support") made it possible for tx_wr.num_sge to be != 1 -- this happens if send gather support is enabled. However, the code in the connected mode post_send() function assumes the old invariant, namely that tx_wr.num_sge is always 1. Fix this by explicitly setting tx_wr.num_sge to 1 in the CM post_send(). Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 52b1bebfa744..4e8d0281f8bc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -637,6 +637,7 @@ static inline int post_send(struct ipoib_dev_priv *priv, priv->tx_sge[0].addr = addr; priv->tx_sge[0].length = len; + priv->tx_wr.num_sge = 1; priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM; return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr); -- cgit From 7c0ea45be4f114d85ee35caeead8e1660699c46f Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 11 Mar 2008 16:56:47 +0800 Subject: ACPI: Ignore _BQC object when registering backlight device According to acpi spec , the objects of _BCL and _BCM are required if integrated LCD is present and supports brightness level .The _BQC is the optional object. So the _BQC object is ignored when the backlight device is registered in ACPI video driver. http://bugzilla.kernel.org/show_bug.cgi?id=10206 Signed-off-by: Zhao Yakui Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 12cce69b5441..ace958cb3894 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) kfree(obj); - if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ + if (device->cap._BCL && device->cap._BCM && max_level > 0) { int result; static int count = 0; char *name; -- cgit From a82f7119fd940c1505fc9fdf93d835fa52bc075d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Mar 2008 00:34:57 +0100 Subject: Hibernation: Fix mark_nosave_pages() There is a problem in the hibernation code that triggers on some NUMA systems on which pfn_valid() returns 'true' for some PFNs that don't belong to any zone. Namely, there is a BUG_ON() in memory_bm_find_bit() that triggers for PFNs not belonging to any zone and passing the pfn_valid() test. On the affected systems it triggers when we mark PFNs reported by the platform as not saveable, because the PFNs in question belong to a region mapped directly using iorepam() (i.e. the ACPI data area) and they pass the pfn_valid() test. Modify memory_bm_find_bit() so that it returns an error if given PFN doesn't belong to any zone instead of crashing the kernel and ignore the result returned by it in mark_nosave_pages(), while marking the "nosave" memory regions. This doesn't affect the hibernation functionality, as we won't touch the PFNs in question anyway. http://bugzilla.kernel.org/show_bug.cgi?id=9966 . Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- kernel/power/snapshot.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 72a020cabb4c..5f91a07c4eac 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) * of @bm->cur_zone_bm are updated. */ -static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, +static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, void **addr, unsigned int *bit_nr) { struct zone_bitmap *zone_bm; @@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) { zone_bm = zone_bm->next; - BUG_ON(!zone_bm); + if (!zone_bm) + return -EFAULT; } bm->cur.zone_bm = zone_bm; } @@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, pfn -= bb->start_pfn; *bit_nr = pfn % BM_BITS_PER_CHUNK; *addr = bb->data + pfn / BM_BITS_PER_CHUNK; + return 0; } static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) { void *addr; unsigned int bit; + int error; - memory_bm_find_bit(bm, pfn, &addr, &bit); + error = memory_bm_find_bit(bm, pfn, &addr, &bit); + BUG_ON(error); set_bit(bit, addr); } +static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) +{ + void *addr; + unsigned int bit; + int error; + + error = memory_bm_find_bit(bm, pfn, &addr, &bit); + if (!error) + set_bit(bit, addr); + return error; +} + static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) { void *addr; unsigned int bit; + int error; - memory_bm_find_bit(bm, pfn, &addr, &bit); + error = memory_bm_find_bit(bm, pfn, &addr, &bit); + BUG_ON(error); clear_bit(bit, addr); } @@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) { void *addr; unsigned int bit; + int error; - memory_bm_find_bit(bm, pfn, &addr, &bit); + error = memory_bm_find_bit(bm, pfn, &addr, &bit); + BUG_ON(error); return test_bit(bit, addr); } @@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm) region->end_pfn << PAGE_SHIFT); for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++) - if (pfn_valid(pfn)) - memory_bm_set_bit(bm, pfn); + if (pfn_valid(pfn)) { + /* + * It is safe to ignore the result of + * mem_bm_set_bit_check() here, since we won't + * touch the PFNs for which the error is + * returned anyway. + */ + mem_bm_set_bit_check(bm, pfn); + } } } -- cgit From 391df5dce30a5aab477b9e55ea65a3e83bae96b1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 11 Mar 2008 13:45:15 -0700 Subject: ACPI: add _PRT quirks to work around broken firmware This patch works around incorrect _PRT (PCI interrupt routing) information from firmware. This does not fix any regressions and can wait for the next kernel release. On the Medion MD9580-F laptop, the BIOS says the builtin RTL8139 NIC interrupt at 00:09.0[A] is connected to \_SB.PCI0.ISA.LNKA, but it's really connected to \_SB.PCI0.ISA.LNKB. Before this patch, the workaround was to use "pci=routeirq". More details at http://bugzilla.kernel.org/show_bug.cgi?id=4773. On the Dell OptiPlex GX1, the BIOS says the PCI slot interrupt 00:0d[A] is connected to LNKB, but it's really connected to LNKA. Before this patch, the workaround was to use "pci=routeirq". Pierre Ossman tested a previous version of this patch and confirmed that it fixed the problem. More details at http://bugzilla.kernel.org/show_bug.cgi?id=5044. On the HP t5710 thin client, the BIOS says the builtin Radeon video interrupt at 01:00[A] is connected to LNK1, but it's really connected to LNK3. The previous workaround was to use a custom DSDT. I tested this patch and verified that it fixes the problem. More details at http://bugzilla.kernel.org/show_bug.cgi?id=10138. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 7f19859580c7..7af414a3c63e 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -25,6 +25,7 @@ */ +#include #include #include #include @@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, return NULL; } +/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ +static struct dmi_system_id medion_md9580[] = { + { + .ident = "Medion MD9580-F laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), + DMI_MATCH(DMI_PRODUCT_NAME, "A555"), + }, + }, + { } +}; + +/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */ +static struct dmi_system_id dell_optiplex[] = { + { + .ident = "Dell Optiplex GX1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"), + }, + }, + { } +}; + +/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */ +static struct dmi_system_id hp_t5710[] = { + { + .ident = "HP t5710", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"), + DMI_MATCH(DMI_BOARD_NAME, "098Ch"), + }, + }, + { } +}; + +struct prt_quirk { + struct dmi_system_id *system; + unsigned int segment; + unsigned int bus; + unsigned int device; + unsigned char pin; + char *source; /* according to BIOS */ + char *actual_source; +}; + +/* + * These systems have incorrect _PRT entries. The BIOS claims the PCI + * interrupt at the listed segment/bus/device/pin is connected to the first + * link device, but it is actually connected to the second. + */ +static struct prt_quirk prt_quirks[] = { + { medion_md9580, 0, 0, 9, 'A', + "\\_SB_.PCI0.ISA.LNKA", + "\\_SB_.PCI0.ISA.LNKB"}, + { dell_optiplex, 0, 0, 0xd, 'A', + "\\_SB_.LNKB", + "\\_SB_.LNKA"}, + { hp_t5710, 0, 0, 1, 'A', + "\\_SB_.PCI0.LNK1", + "\\_SB_.PCI0.LNK3"}, +}; + +static void +do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) +{ + int i; + struct prt_quirk *quirk; + + for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) { + quirk = &prt_quirks[i]; + + /* All current quirks involve link devices, not GSIs */ + if (!prt->source) + continue; + + if (dmi_check_system(quirk->system) && + entry->id.segment == quirk->segment && + entry->id.bus == quirk->bus && + entry->id.device == quirk->device && + entry->pin + 'A' == quirk->pin && + !strcmp(prt->source, quirk->source) && + strlen(prt->source) >= strlen(quirk->actual_source)) { + printk(KERN_WARNING PREFIX "firmware reports " + "%04x:%02x:%02x[%c] connected to %s; " + "changing to %s\n", + entry->id.segment, entry->id.bus, + entry->id.device, 'A' + entry->pin, + prt->source, quirk->actual_source); + strcpy(prt->source, quirk->actual_source); + } + } +} + static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, struct acpi_pci_routing_table *prt) @@ -96,6 +192,8 @@ acpi_pci_irq_add_entry(acpi_handle handle, entry->id.function = prt->address & 0xFFFF; entry->pin = prt->pin; + do_prt_fixups(entry, prt); + /* * Type 1: Dynamic * --------------- -- cgit From b6a163875935ce8e8e85901a7f2b68f7a314d914 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 12 Mar 2008 01:06:24 +0100 Subject: ACPICA: Warn if packages with invalid references are evaluated And return an error to avoid NULL pointer access by the caller Lin Ming's patch avoids corrupted mem access when BIOS has invalid references included, the handle is now zero instead of corrupted. Signed-off-by: Thomas Renninger Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/utils.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index eba55b7d6c95..44ea60cf21c0 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -407,6 +407,12 @@ acpi_evaluate_reference(acpi_handle handle, break; } + if (!element->reference.handle) { + printk(KERN_WARNING PREFIX "Invalid reference in" + " package %s\n", pathname); + status = AE_NULL_ENTRY; + break; + } /* Get the acpi_handle. */ list->handles[i] = element->reference.handle; -- cgit From a09a20b526fde0611b49b76521e3c546a47216a5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Mar 2008 13:41:26 -0800 Subject: laptops: move laptop-mode.txt to Documentation/laptops/ Move laptop-mode.txt into the laptops/ sub-directory to consolidate laptop doc files there. Update references to the file's location. Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- Documentation/00-INDEX | 2 - Documentation/filesystems/proc.txt | 4 +- Documentation/laptop-mode.txt | 950 ---------------------------------- Documentation/laptops/00-INDEX | 2 + Documentation/laptops/laptop-mode.txt | 950 ++++++++++++++++++++++++++++++++++ 5 files changed, 954 insertions(+), 954 deletions(-) delete mode 100644 Documentation/laptop-mode.txt create mode 100644 Documentation/laptops/laptop-mode.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 042073f656e5..1d51c0c57811 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -225,8 +225,6 @@ kprobes.txt - documents the kernel probes debugging feature. kref.txt - docs on adding reference counters (krefs) to kernel objects. -laptop-mode.txt - - how to conserve battery power using laptop-mode. laptops/ - directory with laptop related info and laptop driver documentation. ldm.txt diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 5681e2fa1496..518ebe609e2b 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1506,13 +1506,13 @@ laptop_mode ----------- laptop_mode is a knob that controls "laptop mode". All the things that are -controlled by this knob are discussed in Documentation/laptop-mode.txt. +controlled by this knob are discussed in Documentation/laptops/laptop-mode.txt. block_dump ---------- block_dump enables block I/O debugging when set to a nonzero value. More -information on block I/O debugging is in Documentation/laptop-mode.txt. +information on block I/O debugging is in Documentation/laptops/laptop-mode.txt. swap_token_timeout ------------------ diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt deleted file mode 100644 index eeedee11c8c2..000000000000 --- a/Documentation/laptop-mode.txt +++ /dev/null @@ -1,950 +0,0 @@ -How to conserve battery power using laptop-mode ------------------------------------------------ - -Document Author: Bart Samwel (bart@samwel.tk) -Date created: January 2, 2004 -Last modified: December 06, 2004 - -Introduction ------------- - -Laptop mode is used to minimize the time that the hard disk needs to be spun up, -to conserve battery power on laptops. It has been reported to cause significant -power savings. - -Contents --------- - -* Introduction -* Installation -* Caveats -* The Details -* Tips & Tricks -* Control script -* ACPI integration -* Monitoring tool - - -Installation ------------- - -To use laptop mode, you don't need to set any kernel configuration options -or anything. Simply install all the files included in this document, and -laptop mode will automatically be started when you're on battery. For -your convenience, a tarball containing an installer can be downloaded at: - -http://www.samwel.tk/laptop_mode/laptop_mode/ - -To configure laptop mode, you need to edit the configuration file, which is -located in /etc/default/laptop-mode on Debian-based systems, or in -/etc/sysconfig/laptop-mode on other systems. - -Unfortunately, automatic enabling of laptop mode does not work for -laptops that don't have ACPI. On those laptops, you need to start laptop -mode manually. To start laptop mode, run "laptop_mode start", and to -stop it, run "laptop_mode stop". (Note: The laptop mode tools package now -has experimental support for APM, you might want to try that first.) - - -Caveats -------- - -* The downside of laptop mode is that you have a chance of losing up to 10 - minutes of work. If you cannot afford this, don't use it! The supplied ACPI - scripts automatically turn off laptop mode when the battery almost runs out, - so that you won't lose any data at the end of your battery life. - -* Most desktop hard drives have a very limited lifetime measured in spindown - cycles, typically about 50.000 times (it's usually listed on the spec sheet). - Check your drive's rating, and don't wear down your drive's lifetime if you - don't need to. - -* If you mount some of your ext3/reiserfs filesystems with the -n option, then - the control script will not be able to remount them correctly. You must set - DO_REMOUNTS=0 in the control script, otherwise it will remount them with the - wrong options -- or it will fail because it cannot write to /etc/mtab. - -* If you have your filesystems listed as type "auto" in fstab, like I did, then - the control script will not recognize them as filesystems that need remounting. - You must list the filesystems with their true type instead. - -* It has been reported that some versions of the mutt mail client use file access - times to determine whether a folder contains new mail. If you use mutt and - experience this, you must disable the noatime remounting by setting the option - DO_REMOUNT_NOATIME to 0 in the configuration file. - - -The Details ------------ - -Laptop mode is controlled by the knob /proc/sys/vm/laptop_mode. This knob is -present for all kernels that have the laptop mode patch, regardless of any -configuration options. When the knob is set, any physical disk I/O (that might -have caused the hard disk to spin up) causes Linux to flush all dirty blocks. The -result of this is that after a disk has spun down, it will not be spun up -anymore to write dirty blocks, because those blocks had already been written -immediately after the most recent read operation. The value of the laptop_mode -knob determines the time between the occurrence of disk I/O and when the flush -is triggered. A sensible value for the knob is 5 seconds. Setting the knob to -0 disables laptop mode. - -To increase the effectiveness of the laptop_mode strategy, the laptop_mode -control script increases dirty_expire_centisecs and dirty_writeback_centisecs in -/proc/sys/vm to about 10 minutes (by default), which means that pages that are -dirtied are not forced to be written to disk as often. The control script also -changes the dirty background ratio, so that background writeback of dirty pages -is not done anymore. Combined with a higher commit value (also 10 minutes) for -ext3 or ReiserFS filesystems (also done automatically by the control script), -this results in concentration of disk activity in a small time interval which -occurs only once every 10 minutes, or whenever the disk is forced to spin up by -a cache miss. The disk can then be spun down in the periods of inactivity. - -If you want to find out which process caused the disk to spin up, you can -gather information by setting the flag /proc/sys/vm/block_dump. When this flag -is set, Linux reports all disk read and write operations that take place, and -all block dirtyings done to files. This makes it possible to debug why a disk -needs to spin up, and to increase battery life even more. The output of -block_dump is written to the kernel output, and it can be retrieved using -"dmesg". When you use block_dump and your kernel logging level also includes -kernel debugging messages, you probably want to turn off klogd, otherwise -the output of block_dump will be logged, causing disk activity that is not -normally there. - - -Configuration -------------- - -The laptop mode configuration file is located in /etc/default/laptop-mode on -Debian-based systems, or in /etc/sysconfig/laptop-mode on other systems. It -contains the following options: - -MAX_AGE: - -Maximum time, in seconds, of hard drive spindown time that you are -comfortable with. Worst case, it's possible that you could lose this -amount of work if your battery fails while you're in laptop mode. - -MINIMUM_BATTERY_MINUTES: - -Automatically disable laptop mode if the remaining number of minutes of -battery power is less than this value. Default is 10 minutes. - -AC_HD/BATT_HD: - -The idle timeout that should be set on your hard drive when laptop mode -is active (BATT_HD) and when it is not active (AC_HD). The defaults are -20 seconds (value 4) for BATT_HD and 2 hours (value 244) for AC_HD. The -possible values are those listed in the manual page for "hdparm" for the -"-S" option. - -HD: - -The devices for which the spindown timeout should be adjusted by laptop mode. -Default is /dev/hda. If you specify multiple devices, separate them by a space. - -READAHEAD: - -Disk readahead, in 512-byte sectors, while laptop mode is active. A large -readahead can prevent disk accesses for things like executable pages (which are -loaded on demand while the application executes) and sequentially accessed data -(MP3s). - -DO_REMOUNTS: - -The control script automatically remounts any mounted journaled filesystems -with appropriate commit interval options. When this option is set to 0, this -feature is disabled. - -DO_REMOUNT_NOATIME: - -When remounting, should the filesystems be remounted with the noatime option? -Normally, this is set to "1" (enabled), but there may be programs that require -access time recording. - -DIRTY_RATIO: - -The percentage of memory that is allowed to contain "dirty" or unsaved data -before a writeback is forced, while laptop mode is active. Corresponds to -the /proc/sys/vm/dirty_ratio sysctl. - -DIRTY_BACKGROUND_RATIO: - -The percentage of memory that is allowed to contain "dirty" or unsaved data -after a forced writeback is done due to an exceeding of DIRTY_RATIO. Set -this nice and low. This corresponds to the /proc/sys/vm/dirty_background_ratio -sysctl. - -Note that the behaviour of dirty_background_ratio is quite different -when laptop mode is active and when it isn't. When laptop mode is inactive, -dirty_background_ratio is the threshold percentage at which background writeouts -start taking place. When laptop mode is active, however, background writeouts -are disabled, and the dirty_background_ratio only determines how much writeback -is done when dirty_ratio is reached. - -DO_CPU: - -Enable CPU frequency scaling when in laptop mode. (Requires CPUFreq to be setup. -See Documentation/cpu-freq/user-guide.txt for more info. Disabled by default.) - -CPU_MAXFREQ: - -When on battery, what is the maximum CPU speed that the system should use? Legal -values are "slowest" for the slowest speed that your CPU is able to operate at, -or a value listed in /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies. - - -Tips & Tricks -------------- - -* Bartek Kania reports getting up to 50 minutes of extra battery life (on top - of his regular 3 to 3.5 hours) using a spindown time of 5 seconds (BATT_HD=1). - -* You can spin down the disk while playing MP3, by setting disk readahead - to 8MB (READAHEAD=16384). Effectively, the disk will read a complete MP3 at - once, and will then spin down while the MP3 is playing. (Thanks to Bartek - Kania.) - -* Drew Scott Daniels observed: "I don't know why, but when I decrease the number - of colours that my display uses it consumes less battery power. I've seen - this on powerbooks too. I hope that this is a piece of information that - might be useful to the Laptop Mode patch or it's users." - -* In syslog.conf, you can prefix entries with a dash ``-'' to omit syncing the - file after every logging. When you're using laptop-mode and your disk doesn't - spin down, this is a likely culprit. - -* Richard Atterer observed that laptop mode does not work well with noflushd - (http://noflushd.sourceforge.net/), it seems that noflushd prevents laptop-mode - from doing its thing. - -* If you're worried about your data, you might want to consider using a USB - memory stick or something like that as a "working area". (Be aware though - that flash memory can only handle a limited number of writes, and overuse - may wear out your memory stick pretty quickly. Do _not_ use journalling - filesystems on flash memory sticks.) - - -Configuration file for control and ACPI battery scripts -------------------------------------------------------- - -This allows the tunables to be changed for the scripts via an external -configuration file - -It should be installed as /etc/default/laptop-mode on Debian, and as -/etc/sysconfig/laptop-mode on Red Hat, SUSE, Mandrake, and other work-alikes. - ---------------------CONFIG FILE BEGIN------------------------------------------- -# Maximum time, in seconds, of hard drive spindown time that you are -# comfortable with. Worst case, it's possible that you could lose this -# amount of work if your battery fails you while in laptop mode. -#MAX_AGE=600 - -# Automatically disable laptop mode when the number of minutes of battery -# that you have left goes below this threshold. -MINIMUM_BATTERY_MINUTES=10 - -# Read-ahead, in 512-byte sectors. You can spin down the disk while playing MP3/OGG -# by setting the disk readahead to 8MB (READAHEAD=16384). Effectively, the disk -# will read a complete MP3 at once, and will then spin down while the MP3/OGG is -# playing. -#READAHEAD=4096 - -# Shall we remount journaled fs. with appropriate commit interval? (1=yes) -#DO_REMOUNTS=1 - -# And shall we add the "noatime" option to that as well? (1=yes) -#DO_REMOUNT_NOATIME=1 - -# Dirty synchronous ratio. At this percentage of dirty pages the process -# which -# calls write() does its own writeback -#DIRTY_RATIO=40 - -# -# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio. Set this nice and low, so once -# some writeout has commenced, we do a lot of it. -# -#DIRTY_BACKGROUND_RATIO=5 - -# kernel default dirty buffer age -#DEF_AGE=30 -#DEF_UPDATE=5 -#DEF_DIRTY_BACKGROUND_RATIO=10 -#DEF_DIRTY_RATIO=40 -#DEF_XFS_AGE_BUFFER=15 -#DEF_XFS_SYNC_INTERVAL=30 -#DEF_XFS_BUFD_INTERVAL=1 - -# This must be adjusted manually to the value of HZ in the running kernel -# on 2.4, until the XFS people change their 2.4 external interfaces to work in -# centisecs. This can be automated, but it's a work in progress that still -# needs# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for -# external interfaces, and that is currently always set to 100. So you don't -# need to change this on 2.6. -#XFS_HZ=100 - -# Should the maximum CPU frequency be adjusted down while on battery? -# Requires CPUFreq to be setup. -# See Documentation/cpu-freq/user-guide.txt for more info -#DO_CPU=0 - -# When on battery what is the maximum CPU speed that the system should -# use? Legal values are "slowest" for the slowest speed that your -# CPU is able to operate at, or a value listed in: -# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies -# Only applicable if DO_CPU=1. -#CPU_MAXFREQ=slowest - -# Idle timeout for your hard drive (man hdparm for valid values, -S option) -# Default is 2 hours on AC (AC_HD=244) and 20 seconds for battery (BATT_HD=4). -#AC_HD=244 -#BATT_HD=4 - -# The drives for which to adjust the idle timeout. Separate them by a space, -# e.g. HD="/dev/hda /dev/hdb". -#HD="/dev/hda" - -# Set the spindown timeout on a hard drive? -#DO_HD=1 - ---------------------CONFIG FILE END--------------------------------------------- - - -Control script --------------- - -Please note that this control script works for the Linux 2.4 and 2.6 series (thanks -to Kiko Piris). - ---------------------CONTROL SCRIPT BEGIN---------------------------------------- -#!/bin/bash - -# start or stop laptop_mode, best run by a power management daemon when -# ac gets connected/disconnected from a laptop -# -# install as /sbin/laptop_mode -# -# Contributors to this script: Kiko Piris -# Bart Samwel -# Micha Feigin -# Andrew Morton -# Herve Eychenne -# Dax Kelson -# -# Original Linux 2.4 version by: Jens Axboe - -############################################################################# - -# Source config -if [ -f /etc/default/laptop-mode ] ; then - # Debian - . /etc/default/laptop-mode -elif [ -f /etc/sysconfig/laptop-mode ] ; then - # Others - . /etc/sysconfig/laptop-mode -fi - -# Don't raise an error if the config file is incomplete -# set defaults instead: - -# Maximum time, in seconds, of hard drive spindown time that you are -# comfortable with. Worst case, it's possible that you could lose this -# amount of work if your battery fails you while in laptop mode. -MAX_AGE=${MAX_AGE:-'600'} - -# Read-ahead, in kilobytes -READAHEAD=${READAHEAD:-'4096'} - -# Shall we remount journaled fs. with appropriate commit interval? (1=yes) -DO_REMOUNTS=${DO_REMOUNTS:-'1'} - -# And shall we add the "noatime" option to that as well? (1=yes) -DO_REMOUNT_NOATIME=${DO_REMOUNT_NOATIME:-'1'} - -# Shall we adjust the idle timeout on a hard drive? -DO_HD=${DO_HD:-'1'} - -# Adjust idle timeout on which hard drive? -HD="${HD:-'/dev/hda'}" - -# spindown time for HD (hdparm -S values) -AC_HD=${AC_HD:-'244'} -BATT_HD=${BATT_HD:-'4'} - -# Dirty synchronous ratio. At this percentage of dirty pages the process which -# calls write() does its own writeback -DIRTY_RATIO=${DIRTY_RATIO:-'40'} - -# cpu frequency scaling -# See Documentation/cpu-freq/user-guide.txt for more info -DO_CPU=${CPU_MANAGE:-'0'} -CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'} - -# -# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio. Set this nice and low, so once -# some writeout has commenced, we do a lot of it. -# -DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'} - -# kernel default dirty buffer age -DEF_AGE=${DEF_AGE:-'30'} -DEF_UPDATE=${DEF_UPDATE:-'5'} -DEF_DIRTY_BACKGROUND_RATIO=${DEF_DIRTY_BACKGROUND_RATIO:-'10'} -DEF_DIRTY_RATIO=${DEF_DIRTY_RATIO:-'40'} -DEF_XFS_AGE_BUFFER=${DEF_XFS_AGE_BUFFER:-'15'} -DEF_XFS_SYNC_INTERVAL=${DEF_XFS_SYNC_INTERVAL:-'30'} -DEF_XFS_BUFD_INTERVAL=${DEF_XFS_BUFD_INTERVAL:-'1'} - -# This must be adjusted manually to the value of HZ in the running kernel -# on 2.4, until the XFS people change their 2.4 external interfaces to work in -# centisecs. This can be automated, but it's a work in progress that still needs -# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for external -# interfaces, and that is currently always set to 100. So you don't need to -# change this on 2.6. -XFS_HZ=${XFS_HZ:-'100'} - -############################################################################# - -KLEVEL="$(uname -r | - { - IFS='.' read a b c - echo $a.$b - } -)" -case "$KLEVEL" in - "2.4"|"2.6") - ;; - *) - echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2 - exit 1 - ;; -esac - -if [ ! -e /proc/sys/vm/laptop_mode ] ; then - echo "Kernel is not patched with laptop_mode patch." >&2 - exit 1 -fi - -if [ ! -w /proc/sys/vm/laptop_mode ] ; then - echo "You do not have enough privileges to enable laptop_mode." >&2 - exit 1 -fi - -# Remove an option (the first parameter) of the form option= from -# a mount options string (the rest of the parameters). -parse_mount_opts () { - OPT="$1" - shift - echo ",$*," | sed \ - -e 's/,'"$OPT"'=[0-9]*,/,/g' \ - -e 's/,,*/,/g' \ - -e 's/^,//' \ - -e 's/,$//' -} - -# Remove an option (the first parameter) without any arguments from -# a mount option string (the rest of the parameters). -parse_nonumber_mount_opts () { - OPT="$1" - shift - echo ",$*," | sed \ - -e 's/,'"$OPT"',/,/g' \ - -e 's/,,*/,/g' \ - -e 's/^,//' \ - -e 's/,$//' -} - -# Find out the state of a yes/no option (e.g. "atime"/"noatime") in -# fstab for a given filesystem, and use this state to replace the -# value of the option in another mount options string. The device -# is the first argument, the option name the second, and the default -# value the third. The remainder is the mount options string. -# -# Example: -# parse_yesno_opts_wfstab /dev/hda1 atime atime defaults,noatime -# -# If fstab contains, say, "rw" for this filesystem, then the result -# will be "defaults,atime". -parse_yesno_opts_wfstab () { - L_DEV="$1" - OPT="$2" - DEF_OPT="$3" - shift 3 - L_OPTS="$*" - PARSEDOPTS1="$(parse_nonumber_mount_opts $OPT $L_OPTS)" - PARSEDOPTS1="$(parse_nonumber_mount_opts no$OPT $PARSEDOPTS1)" - # Watch for a default atime in fstab - FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)" - if echo "$FSTAB_OPTS" | grep "$OPT" > /dev/null ; then - # option specified in fstab: extract the value and use it - if echo "$FSTAB_OPTS" | grep "no$OPT" > /dev/null ; then - echo "$PARSEDOPTS1,no$OPT" - else - # no$OPT not found -- so we must have $OPT. - echo "$PARSEDOPTS1,$OPT" - fi - else - # option not specified in fstab -- choose the default. - echo "$PARSEDOPTS1,$DEF_OPT" - fi -} - -# Find out the state of a numbered option (e.g. "commit=NNN") in -# fstab for a given filesystem, and use this state to replace the -# value of the option in another mount options string. The device -# is the first argument, and the option name the second. The -# remainder is the mount options string in which the replacement -# must be done. -# -# Example: -# parse_mount_opts_wfstab /dev/hda1 commit defaults,commit=7 -# -# If fstab contains, say, "commit=3,rw" for this filesystem, then the -# result will be "rw,commit=3". -parse_mount_opts_wfstab () { - L_DEV="$1" - OPT="$2" - shift 2 - L_OPTS="$*" - PARSEDOPTS1="$(parse_mount_opts $OPT $L_OPTS)" - # Watch for a default commit in fstab - FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)" - if echo "$FSTAB_OPTS" | grep "$OPT=" > /dev/null ; then - # option specified in fstab: extract the value, and use it - echo -n "$PARSEDOPTS1,$OPT=" - echo ",$FSTAB_OPTS," | sed \ - -e 's/.*,'"$OPT"'=//' \ - -e 's/,.*//' - else - # option not specified in fstab: set it to 0 - echo "$PARSEDOPTS1,$OPT=0" - fi -} - -deduce_fstype () { - MP="$1" - # My root filesystem unfortunately has - # type "unknown" in /etc/mtab. If we encounter - # "unknown", we try to get the type from fstab. - cat /etc/fstab | - grep -v '^#' | - while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do - if [ "$FSTAB_MP" = "$MP" ]; then - echo $FSTAB_FST - exit 0 - fi - done -} - -if [ $DO_REMOUNT_NOATIME -eq 1 ] ; then - NOATIME_OPT=",noatime" -fi - -case "$1" in - start) - AGE=$((100*$MAX_AGE)) - XFS_AGE=$(($XFS_HZ*$MAX_AGE)) - echo -n "Starting laptop_mode" - - if [ -d /proc/sys/vm/pagebuf ] ; then - # (For 2.4 and early 2.6.) - # This only needs to be set, not reset -- it is only used when - # laptop mode is enabled. - echo $XFS_AGE > /proc/sys/vm/pagebuf/lm_flush_age - echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval - elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then - # (A couple of early 2.6 laptop mode patches had these.) - # The same goes for these. - echo $XFS_AGE > /proc/sys/fs/xfs/lm_age_buffer - echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval - elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then - # (2.6.6) - # But not for these -- they are also used in normal - # operation. - echo $XFS_AGE > /proc/sys/fs/xfs/age_buffer - echo $XFS_AGE > /proc/sys/fs/xfs/sync_interval - elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then - # (2.6.7 upwards) - # And not for these either. These are in centisecs, - # not USER_HZ, so we have to use $AGE, not $XFS_AGE. - echo $AGE > /proc/sys/fs/xfs/age_buffer_centisecs - echo $AGE > /proc/sys/fs/xfs/xfssyncd_centisecs - echo 3000 > /proc/sys/fs/xfs/xfsbufd_centisecs - fi - - case "$KLEVEL" in - "2.4") - echo 1 > /proc/sys/vm/laptop_mode - echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush - ;; - "2.6") - echo 5 > /proc/sys/vm/laptop_mode - echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs - echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs - echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_ratio - echo "$DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio - ;; - esac - if [ $DO_REMOUNTS -eq 1 ]; then - cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do - PARSEDOPTS="$(parse_mount_opts "$OPTS")" - if [ "$FST" = 'unknown' ]; then - FST=$(deduce_fstype $MP) - fi - case "$FST" in - "ext3"|"reiserfs") - PARSEDOPTS="$(parse_mount_opts commit "$OPTS")" - mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT - ;; - "xfs") - mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT - ;; - esac - if [ -b $DEV ] ; then - blockdev --setra $(($READAHEAD * 2)) $DEV - fi - done - fi - if [ $DO_HD -eq 1 ] ; then - for THISHD in $HD ; do - /sbin/hdparm -S $BATT_HD $THISHD > /dev/null 2>&1 - /sbin/hdparm -B 1 $THISHD > /dev/null 2>&1 - done - fi - if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then - if [ $CPU_MAXFREQ = 'slowest' ]; then - CPU_MAXFREQ=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq` - fi - echo $CPU_MAXFREQ > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq - fi - echo "." - ;; - stop) - U_AGE=$((100*$DEF_UPDATE)) - B_AGE=$((100*$DEF_AGE)) - echo -n "Stopping laptop_mode" - echo 0 > /proc/sys/vm/laptop_mode - if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then - # These need to be restored, if there are no lm_*. - echo $(($XFS_HZ*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer - echo $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/sync_interval - elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then - # These need to be restored as well. - echo $((100*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer_centisecs - echo $((100*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/xfssyncd_centisecs - echo $((100*$DEF_XFS_BUFD_INTERVAL)) > /proc/sys/fs/xfs/xfsbufd_centisecs - fi - case "$KLEVEL" in - "2.4") - echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush - ;; - "2.6") - echo "$U_AGE" > /proc/sys/vm/dirty_writeback_centisecs - echo "$B_AGE" > /proc/sys/vm/dirty_expire_centisecs - echo "$DEF_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio - echo "$DEF_DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio - ;; - esac - if [ $DO_REMOUNTS -eq 1 ] ; then - cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do - # Reset commit and atime options to defaults. - if [ "$FST" = 'unknown' ]; then - FST=$(deduce_fstype $MP) - fi - case "$FST" in - "ext3"|"reiserfs") - PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)" - PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)" - mount $DEV -t $FST $MP -o remount,$PARSEDOPTS - ;; - "xfs") - PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $OPTS)" - mount $DEV -t $FST $MP -o remount,$PARSEDOPTS - ;; - esac - if [ -b $DEV ] ; then - blockdev --setra 256 $DEV - fi - done - fi - if [ $DO_HD -eq 1 ] ; then - for THISHD in $HD ; do - /sbin/hdparm -S $AC_HD $THISHD > /dev/null 2>&1 - /sbin/hdparm -B 255 $THISHD > /dev/null 2>&1 - done - fi - if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then - echo `cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq - fi - echo "." - ;; - *) - echo "Usage: $0 {start|stop}" 2>&1 - exit 1 - ;; - -esac - -exit 0 ---------------------CONTROL SCRIPT END------------------------------------------ - - -ACPI integration ----------------- - -Dax Kelson submitted this so that the ACPI acpid daemon will -kick off the laptop_mode script and run hdparm. The part that -automatically disables laptop mode when the battery is low was -written by Jan Topinski. - ------------------/etc/acpi/events/ac_adapter BEGIN------------------------------ -event=ac_adapter -action=/etc/acpi/actions/ac.sh %e -----------------/etc/acpi/events/ac_adapter END--------------------------------- - - ------------------/etc/acpi/events/battery BEGIN--------------------------------- -event=battery.* -action=/etc/acpi/actions/battery.sh %e -----------------/etc/acpi/events/battery END------------------------------------ - - -----------------/etc/acpi/actions/ac.sh BEGIN----------------------------------- -#!/bin/bash - -# ac on/offline event handler - -status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/$2/state` - -case $status in - "on-line") - /sbin/laptop_mode stop - exit 0 - ;; - "off-line") - /sbin/laptop_mode start - exit 0 - ;; -esac ----------------------------/etc/acpi/actions/ac.sh END-------------------------- - - ----------------------------/etc/acpi/actions/battery.sh BEGIN------------------- -#! /bin/bash - -# Automatically disable laptop mode when the battery almost runs out. - -BATT_INFO=/proc/acpi/battery/$2/state - -if [[ -f /proc/sys/vm/laptop_mode ]] -then - LM=`cat /proc/sys/vm/laptop_mode` - if [[ $LM -gt 0 ]] - then - if [[ -f $BATT_INFO ]] - then - # Source the config file only now that we know we need - if [ -f /etc/default/laptop-mode ] ; then - # Debian - . /etc/default/laptop-mode - elif [ -f /etc/sysconfig/laptop-mode ] ; then - # Others - . /etc/sysconfig/laptop-mode - fi - MINIMUM_BATTERY_MINUTES=${MINIMUM_BATTERY_MINUTES:-'10'} - - ACTION="`cat $BATT_INFO | grep charging | cut -c 26-`" - if [[ ACTION -eq "discharging" ]] - then - PRESENT_RATE=`cat $BATT_INFO | grep "present rate:" | sed "s/.* \([0-9][0-9]* \).*/\1/" ` - REMAINING=`cat $BATT_INFO | grep "remaining capacity:" | sed "s/.* \([0-9][0-9]* \).*/\1/" ` - fi - if (($REMAINING * 60 / $PRESENT_RATE < $MINIMUM_BATTERY_MINUTES)) - then - /sbin/laptop_mode stop - fi - else - logger -p daemon.warning "You are using laptop mode and your battery interface $BATT_INFO is missing. This may lead to loss of data when the battery runs out. Check kernel ACPI support and /proc/acpi/battery folder, and edit /etc/acpi/battery.sh to set BATT_INFO to the correct path." - fi - fi -fi ----------------------------/etc/acpi/actions/battery.sh END-------------------- - - -Monitoring tool ---------------- - -Bartek Kania submitted this, it can be used to measure how much time your disk -spends spun up/down. - ----------------------------dslm.c BEGIN----------------------------------------- -/* - * Simple Disk Sleep Monitor - * by Bartek Kania - * Licenced under the GPL - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define D(x) x -#else -#define D(x) -#endif - -int endit = 0; - -/* Check if the disk is in powersave-mode - * Most of the code is stolen from hdparm. - * 1 = active, 0 = standby/sleep, -1 = unknown */ -int check_powermode(int fd) -{ - unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0}; - int state; - - if (ioctl(fd, HDIO_DRIVE_CMD, &args) - && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */ - && ioctl(fd, HDIO_DRIVE_CMD, &args)) { - if (errno != EIO || args[0] != 0 || args[1] != 0) { - state = -1; /* "unknown"; */ - } else - state = 0; /* "sleeping"; */ - } else { - state = (args[2] == 255) ? 1 : 0; - } - D(printf(" drive state is: %d\n", state)); - - return state; -} - -char *state_name(int i) -{ - if (i == -1) return "unknown"; - if (i == 0) return "sleeping"; - if (i == 1) return "active"; - - return "internal error"; -} - -char *myctime(time_t time) -{ - char *ts = ctime(&time); - ts[strlen(ts) - 1] = 0; - - return ts; -} - -void measure(int fd) -{ - time_t start_time; - int last_state; - time_t last_time; - int curr_state; - time_t curr_time = 0; - time_t time_diff; - time_t active_time = 0; - time_t sleep_time = 0; - time_t unknown_time = 0; - time_t total_time = 0; - int changes = 0; - float tmp; - - printf("Starting measurements\n"); - - last_state = check_powermode(fd); - start_time = last_time = time(0); - printf(" System is in state %s\n\n", state_name(last_state)); - - while(!endit) { - sleep(1); - curr_state = check_powermode(fd); - - if (curr_state != last_state || endit) { - changes++; - curr_time = time(0); - time_diff = curr_time - last_time; - - if (last_state == 1) active_time += time_diff; - else if (last_state == 0) sleep_time += time_diff; - else unknown_time += time_diff; - - last_state = curr_state; - last_time = curr_time; - - printf("%s: State-change to %s\n", myctime(curr_time), - state_name(curr_state)); - } - } - changes--; /* Compensate for SIGINT */ - - total_time = time(0) - start_time; - printf("\nTotal running time: %lus\n", curr_time - start_time); - printf(" State changed %d times\n", changes); - - tmp = (float)sleep_time / (float)total_time * 100; - printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp); - tmp = (float)active_time / (float)total_time * 100; - printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp); - tmp = (float)unknown_time / (float)total_time * 100; - printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp); -} - -void ender(int s) -{ - endit = 1; -} - -void usage() -{ - puts("usage: dslm [-w