diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 43 | ||||
-rw-r--r-- | drivers/acpi/acpica/rscreate.c | 27 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 1 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 19 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 27 | ||||
-rw-r--r-- | drivers/acpi/system.c | 11 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 2 | ||||
-rw-r--r-- | drivers/acpi/video.c | 51 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 27 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 81 |
11 files changed, 166 insertions, 127 deletions
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index baa5fc05e124..db307a356f08 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -211,6 +211,12 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) +static unsigned int gts, bfs; +module_param(gts, uint, 0644); +module_param(bfs, uint, 0644); +MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); +MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); + /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state @@ -278,16 +284,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } - /* Execute the _GTS method */ + if (gts) { + /* Execute the _GTS method */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; - status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); + status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } } /* Get current value of PM1A control */ @@ -513,18 +521,19 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) } } - /* Execute the _BFS method */ + if (bfs) { + /* Execute the _BFS method */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; - status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); + status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); + } } - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 663f692fffcf..a3c23d686d5f 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -191,8 +191,6 @@ 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 @@ -261,27 +259,6 @@ 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 ((sub_object_list[3])->common.type != - 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); - } - } - user_prt->pin = (u32) obj_desc->integer.value; /* @@ -304,7 +281,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * 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[source_name_index]; + obj_desc = sub_object_list[2]; if (obj_desc) { switch (obj_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: @@ -378,7 +355,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[source_index_index]; + obj_desc = sub_object_list[3]; if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].SourceIndex) Need Integer, found %s", diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 04e90443eff7..391f331674c7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1065,6 +1065,7 @@ static int acpi_ec_resume(struct acpi_device *device) struct acpi_ec *ec = acpi_driver_data(device); /* Enable use of GPE back */ clear_bit(EC_FLAGS_NO_GPE, &ec->flags); + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); acpi_enable_gpe(NULL, ec->gpe); return 0; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d59f08ecaf16..d916bea729f1 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -353,8 +353,10 @@ static irqreturn_t acpi_irq(int irq, void *dev_id) if (handled) { acpi_irq_handled++; return IRQ_HANDLED; - } else + } else { + acpi_irq_not_handled++; return IRQ_NONE; + } } acpi_status diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ea23c64bd766..07c7d216c89d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -581,6 +581,11 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { struct acpi_processor_cx *cx = &pr->power.states[i]; +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) + /* TSC could halt in idle, so notify users */ + if (tsc_halts_in_c(cx->type)) + mark_tsc_unstable("TSC halts in idle");; +#endif switch (cx->type) { case ACPI_STATE_C1: cx->valid = 1; @@ -657,11 +662,9 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "active state: C%zd\n" "max_cstate: C%d\n" - "bus master activity: %08x\n" "maximum allowed latency: %d usec\n", pr->power.state ? pr->power.state - pr->power.states : 0, - max_cstate, (unsigned)pr->power.bm_activity, - pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)); + max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)); seq_puts(seq, "states:\n"); @@ -871,11 +874,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, kt2 = ktime_get_real(); idle_time = ktime_to_us(ktime_sub(kt2, kt1)); -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) - /* TSC could halt in idle, so notify users */ - if (tsc_halts_in_c(cx->type)) - mark_tsc_unstable("TSC halts in idle");; -#endif sleep_ticks = us_to_pm_timer_ticks(idle_time); /* Tell the scheduler how much we idled: */ @@ -989,11 +987,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, kt2 = ktime_get_real(); idle_time = ktime_to_us(ktime_sub(kt2, kt1)); -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) - /* TSC could halt in idle, so notify users */ - if (tsc_halts_in_c(ACPI_STATE_C3)) - mark_tsc_unstable("TSC halts in idle"); -#endif sleep_ticks = us_to_pm_timer_ticks(idle_time); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d060e6fd7fd5..01574a066534 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -713,6 +713,32 @@ static void acpi_power_off(void) acpi_enter_sleep_state(ACPI_STATE_S5); } +/* + * ACPI 2.0 created the optional _GTS and _BFS, + * but industry adoption has been neither rapid nor broad. + * + * Linux gets into trouble when it executes poorly validated + * paths through the BIOS, so disable _GTS and _BFS by default, + * but do speak up and offer the option to enable them. + */ +void __init acpi_gts_bfs_check(void) +{ + acpi_handle dummy; + + if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__GTS, &dummy))) + { + printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n"); + printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, " + "please notify linux-acpi@vger.kernel.org\n"); + } + if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__BFS, &dummy))) + { + printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n"); + printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, " + "please notify linux-acpi@vger.kernel.org\n"); + } +} + int __init acpi_sleep_init(void) { acpi_status status; @@ -771,5 +797,6 @@ int __init acpi_sleep_init(void) * object can also be evaluated when the system enters S5. */ register_reboot_notifier(&tts_notifier); + acpi_gts_bfs_check(); return 0; } diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index da51f05ef8d8..0944daec064f 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -38,6 +38,7 @@ ACPI_MODULE_NAME("system"); #define ACPI_SYSTEM_DEVICE_NAME "System" u32 acpi_irq_handled; +u32 acpi_irq_not_handled; /* * Make ACPICA version work as module param @@ -214,8 +215,9 @@ err: #define COUNT_GPE 0 #define COUNT_SCI 1 /* acpi_irq_handled */ -#define COUNT_ERROR 2 /* other */ -#define NUM_COUNTERS_EXTRA 3 +#define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ +#define COUNT_ERROR 3 /* other */ +#define NUM_COUNTERS_EXTRA 4 struct event_counter { u32 count; @@ -317,6 +319,8 @@ static ssize_t counter_show(struct kobject *kobj, all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = acpi_irq_handled; + all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = + acpi_irq_not_handled; all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = acpi_gpe_count; @@ -363,6 +367,7 @@ static ssize_t counter_set(struct kobject *kobj, all_counters[i].count = 0; acpi_gpe_count = 0; acpi_irq_handled = 0; + acpi_irq_not_handled = 0; goto end; } @@ -456,6 +461,8 @@ void acpi_irq_stats_init(void) sprintf(buffer, "gpe_all"); else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) sprintf(buffer, "sci"); + else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) + sprintf(buffer, "sci_not"); else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) sprintf(buffer, "error"); else diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9cd15e8c8932..564ea1424288 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -909,7 +909,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) thermal_zone_device_register("acpitz", trips, tz, &acpi_thermal_zone_ops, 0, 0, 0, - tz->polling_frequency); + tz->polling_frequency*100); if (IS_ERR(tz->thermal_zone)) return -ENODEV; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index cd4fb7543a90..1705d947ea09 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -770,10 +770,12 @@ acpi_video_init_brightness(struct acpi_video_device *device) * In this case, the first two elements in _BCL packages * are also supported brightness levels that OS should take care of. */ - for (i = 2; i < count; i++) - if (br->levels[i] == br->levels[0] || - br->levels[i] == br->levels[1]) + for (i = 2; i < count; i++) { + if (br->levels[i] == br->levels[0]) level_ac_battery++; + if (br->levels[i] == br->levels[1]) + level_ac_battery++; + } if (level_ac_battery < 2) { level_ac_battery = 2 - level_ac_battery; @@ -807,12 +809,19 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->flags._BCM_use_index = br->flags._BCL_use_index; /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ - br->curr = max_level; + br->curr = level_old = max_level; + + if (!device->cap._BQC) + goto set_level; + result = acpi_video_device_lcd_get_level_current(device, &level_old); if (result) goto out_free_levels; - result = acpi_video_device_lcd_set_level(device, br->curr); + /* + * Set the level to maximum and check if _BQC uses indexed value + */ + result = acpi_video_device_lcd_set_level(device, max_level); if (result) goto out_free_levels; @@ -820,25 +829,19 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (result) goto out_free_levels; - if ((level != level_old) && !br->flags._BCM_use_index) { - /* Note: - * This piece of code does not work correctly if the current - * brightness levels is 0. - * But I guess boxes that boot with such a dark screen are rare - * and no more code is needed to cover this specifial case. - */ - - if (level_ac_battery != 2) { - /* - * For now, we don't support the _BCL like this: - * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16 - * because we may mess up the index returned by _BQC. - * Plus: we have not got a box like this. - */ - ACPI_ERROR((AE_INFO, "_BCL not supported\n")); - } - br->flags._BQC_use_index = 1; - } + br->flags._BQC_use_index = (level == max_level ? 0 : 1); + + if (!br->flags._BQC_use_index) + goto set_level; + + if (br->flags._BCL_reversed) + level_old = (br->count - 1) - level_old; + level_old = br->levels[level_old]; + +set_level: + result = acpi_video_device_lcd_set_level(device, level_old); + if (result) + goto out_free_levels; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count - 2)); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index d3c92d777bde..552958545f94 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -317,7 +317,8 @@ static void sony_laptop_report_input_event(u8 event) struct input_dev *key_dev = sony_laptop_input.key_dev; struct sony_laptop_keypress kp = { NULL }; - if (event == SONYPI_EVENT_FNKEY_RELEASED) { + if (event == SONYPI_EVENT_FNKEY_RELEASED || + event == SONYPI_EVENT_ANYBUTTON_RELEASED) { /* Nothing, not all VAIOs generate this event */ return; } @@ -905,7 +906,6 @@ static struct sony_nc_event sony_127_events[] = { { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x86, SONYPI_EVENT_PKEY_P5 }, { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, - { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, @@ -1004,6 +1004,7 @@ static int sony_nc_function_setup(struct acpi_device *device) sony_call_snc_handle(0x0100, 0, &result); sony_call_snc_handle(0x0101, 0, &result); sony_call_snc_handle(0x0102, 0x100, &result); + sony_call_snc_handle(0x0127, 0, &result); return 0; } @@ -1040,7 +1041,7 @@ static int sony_nc_resume(struct acpi_device *device) /* set the last requested brightness level */ if (sony_backlight_device && - !sony_backlight_update_status(sony_backlight_device)) + sony_backlight_update_status(sony_backlight_device) < 0) printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); return 0; @@ -1102,8 +1103,11 @@ static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) err = rfkill_register(sony_wifi_rfkill); if (err) rfkill_free(sony_wifi_rfkill); - else + else { sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; + sony_nc_rfkill_set(sony_wifi_rfkill->data, + RFKILL_STATE_UNBLOCKED); + } return err; } @@ -1124,8 +1128,11 @@ static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) err = rfkill_register(sony_bluetooth_rfkill); if (err) rfkill_free(sony_bluetooth_rfkill); - else + else { sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; + sony_nc_rfkill_set(sony_bluetooth_rfkill->data, + RFKILL_STATE_UNBLOCKED); + } return err; } @@ -1145,8 +1152,11 @@ static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) err = rfkill_register(sony_wwan_rfkill); if (err) rfkill_free(sony_wwan_rfkill); - else + else { sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; + sony_nc_rfkill_set(sony_wwan_rfkill->data, + RFKILL_STATE_UNBLOCKED); + } return err; } @@ -1166,8 +1176,11 @@ static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) err = rfkill_register(sony_wimax_rfkill); if (err) rfkill_free(sony_wimax_rfkill); - else + else { sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; + sony_nc_rfkill_set(sony_wimax_rfkill->data, + RFKILL_STATE_UNBLOCKED); + } return err; } diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a40b075743d9..912be65b6261 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -21,7 +21,7 @@ * 02110-1301, USA. */ -#define TPACPI_VERSION "0.22" +#define TPACPI_VERSION "0.23" #define TPACPI_SYSFS_VERSION 0x020300 /* @@ -303,11 +303,17 @@ static u32 dbg_level; static struct workqueue_struct *tpacpi_wq; +enum led_status_t { + TPACPI_LED_OFF = 0, + TPACPI_LED_ON, + TPACPI_LED_BLINK, +}; + /* Special LED class that can defer work */ struct tpacpi_led_classdev { struct led_classdev led_classdev; struct work_struct work; - enum led_brightness new_brightness; + enum led_status_t new_state; unsigned int led; }; @@ -2946,12 +2952,18 @@ static int hotkey_read(char *p) return len; } -static void hotkey_enabledisable_warn(void) +static void hotkey_enabledisable_warn(bool enable) { tpacpi_log_usertask("procfs hotkey enable/disable"); - WARN(1, TPACPI_WARN - "hotkey enable/disable functionality has been " - "removed from the driver. Hotkeys are always enabled.\n"); + if (!WARN((tpacpi_lifecycle == TPACPI_LIFE_RUNNING || !enable), + TPACPI_WARN + "hotkey enable/disable functionality has been " + "removed from the driver. Hotkeys are always " + "enabled\n")) + printk(TPACPI_ERR + "Please remove the hotkey=enable module " + "parameter, it is deprecated. Hotkeys are always " + "enabled\n"); } static int hotkey_write(char *buf) @@ -2971,9 +2983,9 @@ static int hotkey_write(char *buf) res = 0; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "enable") == 0) { - hotkey_enabledisable_warn(); + hotkey_enabledisable_warn(1); } else if (strlencmp(cmd, "disable") == 0) { - hotkey_enabledisable_warn(); + hotkey_enabledisable_warn(0); res = -EPERM; } else if (strlencmp(cmd, "reset") == 0) { mask = hotkey_orig_mask; @@ -4207,7 +4219,7 @@ static void light_set_status_worker(struct work_struct *work) container_of(work, struct tpacpi_led_classdev, work); if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) - light_set_status((data->new_brightness != LED_OFF)); + light_set_status((data->new_state != TPACPI_LED_OFF)); } static void light_sysfs_set(struct led_classdev *led_cdev, @@ -4217,7 +4229,8 @@ static void light_sysfs_set(struct led_classdev *led_cdev, container_of(led_cdev, struct tpacpi_led_classdev, led_classdev); - data->new_brightness = brightness; + data->new_state = (brightness != LED_OFF) ? + TPACPI_LED_ON : TPACPI_LED_OFF; queue_work(tpacpi_wq, &data->work); } @@ -4724,12 +4737,6 @@ enum { /* For TPACPI_LED_OLD */ TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ }; -enum led_status_t { - TPACPI_LED_OFF = 0, - TPACPI_LED_ON, - TPACPI_LED_BLINK, -}; - static enum led_access_mode led_supported; TPACPI_HANDLE(led, ec, "SLED", /* 570 */ @@ -4841,23 +4848,13 @@ static int led_set_status(const unsigned int led, return rc; } -static void led_sysfs_set_status(unsigned int led, - enum led_brightness brightness) -{ - led_set_status(led, - (brightness == LED_OFF) ? - TPACPI_LED_OFF : - (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? - TPACPI_LED_BLINK : TPACPI_LED_ON); -} - static void led_set_status_worker(struct work_struct *work) { struct tpacpi_led_classdev *data = container_of(work, struct tpacpi_led_classdev, work); if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) - led_sysfs_set_status(data->led, data->new_brightness); + led_set_status(data->led, data->new_state); } static void led_sysfs_set(struct led_classdev *led_cdev, @@ -4866,7 +4863,13 @@ static void led_sysfs_set(struct led_classdev *led_cdev, struct tpacpi_led_classdev *data = container_of(led_cdev, struct tpacpi_led_classdev, led_classdev); - data->new_brightness = brightness; + if (brightness == LED_OFF) + data->new_state = TPACPI_LED_OFF; + else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK) + data->new_state = TPACPI_LED_ON; + else + data->new_state = TPACPI_LED_BLINK; + queue_work(tpacpi_wq, &data->work); } @@ -4884,7 +4887,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev, } else if ((*delay_on != 500) || (*delay_off != 500)) return -EINVAL; - data->new_brightness = TPACPI_LED_BLINK; + data->new_state = TPACPI_LED_BLINK; queue_work(tpacpi_wq, &data->work); return 0; @@ -7858,6 +7861,15 @@ static int __init thinkpad_acpi_module_init(void) MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); /* + * This will autoload the driver in almost every ThinkPad + * in widespread use. + * + * Only _VERY_ old models, like the 240, 240x and 570 lack + * the HKEY event interface. + */ +MODULE_DEVICE_TABLE(acpi, ibm_htk_device_ids); + +/* * DMI matching for module autoloading * * See http://thinkwiki.org/wiki/List_of_DMI_IDs @@ -7869,18 +7881,13 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); #define IBM_BIOS_MODULE_ALIAS(__type) \ MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*") -/* Non-ancient thinkpads */ -MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); -MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); - /* Ancient thinkpad BIOSes have to be identified by * BIOS type or model number, and there are far less * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]"); -IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]"); -IBM_BIOS_MODULE_ALIAS("K[UX-Z]"); +IBM_BIOS_MODULE_ALIAS("I[MU]"); /* 570, 570e */ -MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); +MODULE_AUTHOR("Borislav Deianov <borislav@users.sf.net>"); +MODULE_AUTHOR("Henrique de Moraes Holschuh <hmh@hmh.eng.br>"); MODULE_DESCRIPTION(TPACPI_DESC); MODULE_VERSION(TPACPI_VERSION); MODULE_LICENSE("GPL"); |