From 1baa92529b7a675f992ee8b1bab77317590b7aed Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 12 Jun 2008 22:01:32 -0300 Subject: [PATCH] Add patches accepted for 2.6.26-rc6 Signed-off-by: Henrique de Moraes Holschuh --- ...pad-acpi-SW_RADIO-to-SW_RFKILL_ALL-rename.patch | 54 ++ ...nkpad-acpi-fix-initialization-error-paths.patch | 546 +++++++++++++++++++++ ...-acpi-fix-LED-handling-on-older-ThinkPads.patch | 115 +++++ 3 files changed, 715 insertions(+) create mode 100644 releases/upstream/2.6.26-rc6/0001-thinkpad-acpi-SW_RADIO-to-SW_RFKILL_ALL-rename.patch create mode 100644 releases/upstream/2.6.26-rc6/0002-thinkpad-acpi-fix-initialization-error-paths.patch create mode 100644 releases/upstream/2.6.26-rc6/0003-thinkpad-acpi-fix-LED-handling-on-older-ThinkPads.patch diff --git a/releases/upstream/2.6.26-rc6/0001-thinkpad-acpi-SW_RADIO-to-SW_RFKILL_ALL-rename.patch b/releases/upstream/2.6.26-rc6/0001-thinkpad-acpi-SW_RADIO-to-SW_RFKILL_ALL-rename.patch new file mode 100644 index 00000000000..1081be76723 --- /dev/null +++ b/releases/upstream/2.6.26-rc6/0001-thinkpad-acpi-SW_RADIO-to-SW_RFKILL_ALL-rename.patch @@ -0,0 +1,54 @@ +From 197a2cd907e3a5278a1cfd48c86402133f38a9ba Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 3 Jun 2008 23:36:09 -0300 +Subject: thinkpad-acpi: SW_RADIO to SW_RFKILL_ALL rename + +Rename SW_RADIO to SW_RFKILL_ALL in thinkpad-acpi code and docs, following +5adad0133907790c50283bf03271d920d6897043 "Input: rename SW_RADIO to +SW_RFKILL_ALL". + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 2 +- + drivers/misc/thinkpad_acpi.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index 01c6c3d..64b3f14 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -503,7 +503,7 @@ generate input device EV_KEY events. + In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW + events for switches: + +-SW_RADIO T60 and later hardare rfkill rocker switch ++SW_RFKILL_ALL T60 and later hardare rfkill rocker switch + SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A + + Non hot-key ACPI HKEY event map: +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index a0ce0b2..f81e048 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void) + mutex_lock(&tpacpi_inputdev_send_mutex); + + input_report_switch(tpacpi_inputdev, +- SW_RADIO, !!wlsw); ++ SW_RFKILL_ALL, !!wlsw); + input_sync(tpacpi_inputdev); + + mutex_unlock(&tpacpi_inputdev_send_mutex); +@@ -2199,7 +2199,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) + + if (tp_features.hotkey_wlsw) { + set_bit(EV_SW, tpacpi_inputdev->evbit); +- set_bit(SW_RADIO, tpacpi_inputdev->swbit); ++ set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); + } + if (tp_features.hotkey_tablet) { + set_bit(EV_SW, tpacpi_inputdev->evbit); +-- +1.5.5.3 + diff --git a/releases/upstream/2.6.26-rc6/0002-thinkpad-acpi-fix-initialization-error-paths.patch b/releases/upstream/2.6.26-rc6/0002-thinkpad-acpi-fix-initialization-error-paths.patch new file mode 100644 index 00000000000..491cd59bf47 --- /dev/null +++ b/releases/upstream/2.6.26-rc6/0002-thinkpad-acpi-fix-initialization-error-paths.patch @@ -0,0 +1,546 @@ +From 9c0a76e16ee6648f4bd19563e9fe12a4f4fabba1 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 3 Jun 2008 23:36:10 -0300 +Subject: thinkpad-acpi: fix initialization error paths + +Rework some subdriver init and exit handlers, in order to fix some +initialization error paths that were missing, or broken. + +Hitting those bugs should be extremely rare in the real world, but should +that happen, thinkpad-acpi would fail to dealocate some resources and a +reboot might well be needed to be able to load the driver again. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 435 ++++++++++++++++++++++-------------------- + 1 files changed, 229 insertions(+), 206 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index f81e048..58973da 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { + &dev_attr_hotkey_wakeup_hotunplug_complete.attr, + }; + ++static void hotkey_exit(void) ++{ ++#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL ++ hotkey_poll_stop_sync(); ++#endif ++ ++ if (hotkey_dev_attributes) ++ delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); ++ ++ kfree(hotkey_keycode_map); ++ ++ if (tp_features.hotkey) { ++ dbg_printk(TPACPI_DBG_EXIT, ++ "restoring original hot key mask\n"); ++ /* no short-circuit boolean operator below! */ ++ if ((hotkey_mask_set(hotkey_orig_mask) | ++ hotkey_status_set(hotkey_orig_status)) != 0) ++ printk(TPACPI_ERR ++ "failed to restore hot key mask " ++ "to BIOS defaults\n"); ++ } ++} ++ + static int __init hotkey_init(struct ibm_init_struct *iibm) + { + /* Requirements for changing the default keymaps: +@@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) + vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", + str_supported(tp_features.hotkey)); + +- if (tp_features.hotkey) { +- hotkey_dev_attributes = create_attr_set(13, NULL); +- if (!hotkey_dev_attributes) +- return -ENOMEM; +- res = add_many_to_attr_set(hotkey_dev_attributes, +- hotkey_attributes, +- ARRAY_SIZE(hotkey_attributes)); +- if (res) +- return res; ++ if (!tp_features.hotkey) ++ return 1; + +- /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, +- A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking +- for HKEY interface version 0x100 */ +- if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { +- if ((hkeyv >> 8) != 1) { +- printk(TPACPI_ERR "unknown version of the " +- "HKEY interface: 0x%x\n", hkeyv); +- printk(TPACPI_ERR "please report this to %s\n", +- TPACPI_MAIL); +- } else { +- /* +- * MHKV 0x100 in A31, R40, R40e, +- * T4x, X31, and later +- */ +- tp_features.hotkey_mask = 1; +- } ++ hotkey_dev_attributes = create_attr_set(13, NULL); ++ if (!hotkey_dev_attributes) ++ return -ENOMEM; ++ res = add_many_to_attr_set(hotkey_dev_attributes, ++ hotkey_attributes, ++ ARRAY_SIZE(hotkey_attributes)); ++ if (res) ++ goto err_exit; ++ ++ /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, ++ A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking ++ for HKEY interface version 0x100 */ ++ if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { ++ if ((hkeyv >> 8) != 1) { ++ printk(TPACPI_ERR "unknown version of the " ++ "HKEY interface: 0x%x\n", hkeyv); ++ printk(TPACPI_ERR "please report this to %s\n", ++ TPACPI_MAIL); ++ } else { ++ /* ++ * MHKV 0x100 in A31, R40, R40e, ++ * T4x, X31, and later ++ */ ++ tp_features.hotkey_mask = 1; + } ++ } + +- vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", +- str_supported(tp_features.hotkey_mask)); ++ vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", ++ str_supported(tp_features.hotkey_mask)); + +- if (tp_features.hotkey_mask) { +- if (!acpi_evalf(hkey_handle, &hotkey_all_mask, +- "MHKA", "qd")) { +- printk(TPACPI_ERR +- "missing MHKA handler, " +- "please report this to %s\n", +- TPACPI_MAIL); +- /* FN+F12, FN+F4, FN+F3 */ +- hotkey_all_mask = 0x080cU; +- } ++ if (tp_features.hotkey_mask) { ++ if (!acpi_evalf(hkey_handle, &hotkey_all_mask, ++ "MHKA", "qd")) { ++ printk(TPACPI_ERR ++ "missing MHKA handler, " ++ "please report this to %s\n", ++ TPACPI_MAIL); ++ /* FN+F12, FN+F4, FN+F3 */ ++ hotkey_all_mask = 0x080cU; + } ++ } + +- /* hotkey_source_mask *must* be zero for +- * the first hotkey_mask_get */ +- res = hotkey_status_get(&hotkey_orig_status); +- if (!res && tp_features.hotkey_mask) { +- res = hotkey_mask_get(); +- hotkey_orig_mask = hotkey_mask; +- if (!res) { +- res = add_many_to_attr_set( +- hotkey_dev_attributes, +- hotkey_mask_attributes, +- ARRAY_SIZE(hotkey_mask_attributes)); +- } +- } ++ /* hotkey_source_mask *must* be zero for ++ * the first hotkey_mask_get */ ++ res = hotkey_status_get(&hotkey_orig_status); ++ if (res) ++ goto err_exit; ++ ++ if (tp_features.hotkey_mask) { ++ res = hotkey_mask_get(); ++ if (res) ++ goto err_exit; ++ ++ hotkey_orig_mask = hotkey_mask; ++ res = add_many_to_attr_set( ++ hotkey_dev_attributes, ++ hotkey_mask_attributes, ++ ARRAY_SIZE(hotkey_mask_attributes)); ++ if (res) ++ goto err_exit; ++ } + + #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL +- if (tp_features.hotkey_mask) { +- hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK +- & ~hotkey_all_mask; +- } else { +- hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; +- } ++ if (tp_features.hotkey_mask) { ++ hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK ++ & ~hotkey_all_mask; ++ } else { ++ hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; ++ } + +- vdbg_printk(TPACPI_DBG_INIT, +- "hotkey source mask 0x%08x, polling freq %d\n", +- hotkey_source_mask, hotkey_poll_freq); ++ vdbg_printk(TPACPI_DBG_INIT, ++ "hotkey source mask 0x%08x, polling freq %d\n", ++ hotkey_source_mask, hotkey_poll_freq); + #endif + +- /* Not all thinkpads have a hardware radio switch */ +- if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { +- tp_features.hotkey_wlsw = 1; +- printk(TPACPI_INFO +- "radio switch found; radios are %s\n", +- enabled(status, 0)); +- res = add_to_attr_set(hotkey_dev_attributes, +- &dev_attr_hotkey_radio_sw.attr); +- } ++ /* Not all thinkpads have a hardware radio switch */ ++ if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { ++ tp_features.hotkey_wlsw = 1; ++ printk(TPACPI_INFO ++ "radio switch found; radios are %s\n", ++ enabled(status, 0)); ++ res = add_to_attr_set(hotkey_dev_attributes, ++ &dev_attr_hotkey_radio_sw.attr); ++ } + +- /* For X41t, X60t, X61t Tablets... */ +- if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { +- tp_features.hotkey_tablet = 1; +- printk(TPACPI_INFO +- "possible tablet mode switch found; " +- "ThinkPad in %s mode\n", +- (status & TP_HOTKEY_TABLET_MASK)? +- "tablet" : "laptop"); +- res = add_to_attr_set(hotkey_dev_attributes, +- &dev_attr_hotkey_tablet_mode.attr); +- } ++ /* For X41t, X60t, X61t Tablets... */ ++ if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { ++ tp_features.hotkey_tablet = 1; ++ printk(TPACPI_INFO ++ "possible tablet mode switch found; " ++ "ThinkPad in %s mode\n", ++ (status & TP_HOTKEY_TABLET_MASK)? ++ "tablet" : "laptop"); ++ res = add_to_attr_set(hotkey_dev_attributes, ++ &dev_attr_hotkey_tablet_mode.attr); ++ } + +- if (!res) +- res = register_attr_set_with_sysfs( +- hotkey_dev_attributes, +- &tpacpi_pdev->dev.kobj); +- if (res) +- return res; ++ if (!res) ++ res = register_attr_set_with_sysfs( ++ hotkey_dev_attributes, ++ &tpacpi_pdev->dev.kobj); ++ if (res) ++ goto err_exit; + +- /* Set up key map */ ++ /* Set up key map */ + +- hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, +- GFP_KERNEL); +- if (!hotkey_keycode_map) { +- printk(TPACPI_ERR +- "failed to allocate memory for key map\n"); +- return -ENOMEM; +- } ++ hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, ++ GFP_KERNEL); ++ if (!hotkey_keycode_map) { ++ printk(TPACPI_ERR ++ "failed to allocate memory for key map\n"); ++ res = -ENOMEM; ++ goto err_exit; ++ } + +- if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { +- dbg_printk(TPACPI_DBG_INIT, +- "using Lenovo default hot key map\n"); +- memcpy(hotkey_keycode_map, &lenovo_keycode_map, +- TPACPI_HOTKEY_MAP_SIZE); ++ if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { ++ dbg_printk(TPACPI_DBG_INIT, ++ "using Lenovo default hot key map\n"); ++ memcpy(hotkey_keycode_map, &lenovo_keycode_map, ++ TPACPI_HOTKEY_MAP_SIZE); ++ } else { ++ dbg_printk(TPACPI_DBG_INIT, ++ "using IBM default hot key map\n"); ++ memcpy(hotkey_keycode_map, &ibm_keycode_map, ++ TPACPI_HOTKEY_MAP_SIZE); ++ } ++ ++ set_bit(EV_KEY, tpacpi_inputdev->evbit); ++ set_bit(EV_MSC, tpacpi_inputdev->evbit); ++ set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); ++ tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; ++ tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; ++ tpacpi_inputdev->keycode = hotkey_keycode_map; ++ for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { ++ if (hotkey_keycode_map[i] != KEY_RESERVED) { ++ set_bit(hotkey_keycode_map[i], ++ tpacpi_inputdev->keybit); + } else { +- dbg_printk(TPACPI_DBG_INIT, +- "using IBM default hot key map\n"); +- memcpy(hotkey_keycode_map, &ibm_keycode_map, +- TPACPI_HOTKEY_MAP_SIZE); +- } +- +- set_bit(EV_KEY, tpacpi_inputdev->evbit); +- set_bit(EV_MSC, tpacpi_inputdev->evbit); +- set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); +- tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; +- tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; +- tpacpi_inputdev->keycode = hotkey_keycode_map; +- for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { +- if (hotkey_keycode_map[i] != KEY_RESERVED) { +- set_bit(hotkey_keycode_map[i], +- tpacpi_inputdev->keybit); +- } else { +- if (i < sizeof(hotkey_reserved_mask)*8) +- hotkey_reserved_mask |= 1 << i; +- } +- } +- +- if (tp_features.hotkey_wlsw) { +- set_bit(EV_SW, tpacpi_inputdev->evbit); +- set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); +- } +- if (tp_features.hotkey_tablet) { +- set_bit(EV_SW, tpacpi_inputdev->evbit); +- set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); ++ if (i < sizeof(hotkey_reserved_mask)*8) ++ hotkey_reserved_mask |= 1 << i; + } ++ } + +- /* Do not issue duplicate brightness change events to +- * userspace */ +- if (!tp_features.bright_acpimode) +- /* update bright_acpimode... */ +- tpacpi_check_std_acpi_brightness_support(); +- +- if (tp_features.bright_acpimode) { +- printk(TPACPI_INFO +- "This ThinkPad has standard ACPI backlight " +- "brightness control, supported by the ACPI " +- "video driver\n"); +- printk(TPACPI_NOTICE +- "Disabling thinkpad-acpi brightness events " +- "by default...\n"); +- +- /* The hotkey_reserved_mask change below is not +- * necessary while the keys are at KEY_RESERVED in the +- * default map, but better safe than sorry, leave it +- * here as a marker of what we have to do, especially +- * when we finally become able to set this at runtime +- * on response to X.org requests */ +- hotkey_reserved_mask |= +- (1 << TP_ACPI_HOTKEYSCAN_FNHOME) +- | (1 << TP_ACPI_HOTKEYSCAN_FNEND); +- } ++ if (tp_features.hotkey_wlsw) { ++ set_bit(EV_SW, tpacpi_inputdev->evbit); ++ set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); ++ } ++ if (tp_features.hotkey_tablet) { ++ set_bit(EV_SW, tpacpi_inputdev->evbit); ++ set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); ++ } + +- dbg_printk(TPACPI_DBG_INIT, +- "enabling hot key handling\n"); +- res = hotkey_status_set(1); +- if (res) +- return res; +- res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) +- & ~hotkey_reserved_mask) +- | hotkey_orig_mask); +- if (res < 0 && res != -ENXIO) +- return res; ++ /* Do not issue duplicate brightness change events to ++ * userspace */ ++ if (!tp_features.bright_acpimode) ++ /* update bright_acpimode... */ ++ tpacpi_check_std_acpi_brightness_support(); + +- dbg_printk(TPACPI_DBG_INIT, +- "legacy hot key reporting over procfs %s\n", +- (hotkey_report_mode < 2) ? +- "enabled" : "disabled"); ++ if (tp_features.bright_acpimode) { ++ printk(TPACPI_INFO ++ "This ThinkPad has standard ACPI backlight " ++ "brightness control, supported by the ACPI " ++ "video driver\n"); ++ printk(TPACPI_NOTICE ++ "Disabling thinkpad-acpi brightness events " ++ "by default...\n"); ++ ++ /* The hotkey_reserved_mask change below is not ++ * necessary while the keys are at KEY_RESERVED in the ++ * default map, but better safe than sorry, leave it ++ * here as a marker of what we have to do, especially ++ * when we finally become able to set this at runtime ++ * on response to X.org requests */ ++ hotkey_reserved_mask |= ++ (1 << TP_ACPI_HOTKEYSCAN_FNHOME) ++ | (1 << TP_ACPI_HOTKEYSCAN_FNEND); ++ } ++ ++ dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); ++ res = hotkey_status_set(1); ++ if (res) { ++ hotkey_exit(); ++ return res; ++ } ++ res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) ++ & ~hotkey_reserved_mask) ++ | hotkey_orig_mask); ++ if (res < 0 && res != -ENXIO) { ++ hotkey_exit(); ++ return res; ++ } + +- tpacpi_inputdev->open = &hotkey_inputdev_open; +- tpacpi_inputdev->close = &hotkey_inputdev_close; ++ dbg_printk(TPACPI_DBG_INIT, ++ "legacy hot key reporting over procfs %s\n", ++ (hotkey_report_mode < 2) ? ++ "enabled" : "disabled"); + +- hotkey_poll_setup_safe(1); +- tpacpi_input_send_radiosw(); +- tpacpi_input_send_tabletsw(); +- } ++ tpacpi_inputdev->open = &hotkey_inputdev_open; ++ tpacpi_inputdev->close = &hotkey_inputdev_close; + +- return (tp_features.hotkey)? 0 : 1; +-} ++ hotkey_poll_setup_safe(1); ++ tpacpi_input_send_radiosw(); ++ tpacpi_input_send_tabletsw(); + +-static void hotkey_exit(void) +-{ +-#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL +- hotkey_poll_stop_sync(); +-#endif ++ return 0; + +- if (tp_features.hotkey) { +- dbg_printk(TPACPI_DBG_EXIT, +- "restoring original hot key mask\n"); +- /* no short-circuit boolean operator below! */ +- if ((hotkey_mask_set(hotkey_orig_mask) | +- hotkey_status_set(hotkey_orig_status)) != 0) +- printk(TPACPI_ERR +- "failed to restore hot key mask " +- "to BIOS defaults\n"); +- } ++err_exit: ++ delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); ++ hotkey_dev_attributes = NULL; + +- if (hotkey_dev_attributes) { +- delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); +- hotkey_dev_attributes = NULL; +- } ++ return (res < 0)? res : 1; + } + + static void hotkey_notify(struct ibm_struct *ibm, u32 event) +@@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = { + + static int __init light_init(struct ibm_init_struct *iibm) + { +- int rc = 0; ++ int rc; + + vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); + +@@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm) + tp_features.light_status = + acpi_evalf(ec_handle, NULL, "KBLT", "qv"); + +- vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", +- str_supported(tp_features.light)); ++ vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n", ++ str_supported(tp_features.light), ++ str_supported(tp_features.light_status)); + +- if (tp_features.light) { +- rc = led_classdev_register(&tpacpi_pdev->dev, +- &tpacpi_led_thinklight.led_classdev); +- } ++ if (!tp_features.light) ++ return 1; ++ ++ rc = led_classdev_register(&tpacpi_pdev->dev, ++ &tpacpi_led_thinklight.led_classdev); + + if (rc < 0) { + tp_features.light = 0; + tp_features.light_status = 0; +- } else { +- rc = (tp_features.light)? 0 : 1; ++ } else { ++ rc = 0; + } ++ + return rc; + } + +@@ -3978,7 +3998,6 @@ static void led_exit(void) + } + + kfree(tpacpi_leds); +- tpacpi_leds = NULL; + } + + static int __init led_init(struct ibm_init_struct *iibm) +@@ -4802,7 +4821,6 @@ static void brightness_exit(void) + vdbg_printk(TPACPI_DBG_EXIT, + "calling backlight_device_unregister()\n"); + backlight_device_unregister(ibm_backlight_device); +- ibm_backlight_device = NULL; + } + } + +@@ -5764,11 +5782,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) + fan_control_access_mode != TPACPI_FAN_WR_NONE) { + rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, + &fan_attr_group); +- if (!(rc < 0)) +- rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, +- &driver_attr_fan_watchdog); + if (rc < 0) + return rc; ++ ++ rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, ++ &driver_attr_fan_watchdog); ++ if (rc < 0) { ++ sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, ++ &fan_attr_group); ++ return rc; ++ } + return 0; + } else + return 1; +-- +1.5.5.3 + diff --git a/releases/upstream/2.6.26-rc6/0003-thinkpad-acpi-fix-LED-handling-on-older-ThinkPads.patch b/releases/upstream/2.6.26-rc6/0003-thinkpad-acpi-fix-LED-handling-on-older-ThinkPads.patch new file mode 100644 index 00000000000..e37932811c1 --- /dev/null +++ b/releases/upstream/2.6.26-rc6/0003-thinkpad-acpi-fix-LED-handling-on-older-ThinkPads.patch @@ -0,0 +1,115 @@ +From 24e45bbe695719dca8c20e03d386eb6ea86526b5 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 3 Jun 2008 23:36:11 -0300 +Subject: thinkpad-acpi: fix LED handling on older ThinkPads + +The less tested codepaths for LED handling, used on ThinkPads 570, 600e/x, +770e, 770x, A21e, A2xm/p, T20-22, X20 and maybe a few others, would write +data to kernel memory it had no business touching, for leds number 3 and +above. If one is lucky, that illegal write would cause an OOPS, but +chances are it would silently corrupt a byte. + +The problem was introduced in commit af116101, "ACPI: thinkpad-acpi: add +sysfs led class support to thinkpad leds (v3.2)". + +Fix the bug by refactoring the entire code to be far more obvious on what +it wants to do. Also do some defensive "constification". + +Issue reported by Karol Lewandowski (he's an lucky guy +and got an OOPS instead of silent corruption :-) ). + +Root cause of the OOPS identified by Adrian Bunk . +Thanks, Adrian! + +Signed-off-by: Henrique de Moraes Holschuh +Tested-by: Karol Lewandowski +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 55 +++++++++++++++++++++-------------------- + 1 files changed, 28 insertions(+), 27 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 58973da..b596929 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -3853,7 +3853,7 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { + "tpacpi::standby", + }; + +-static int led_get_status(unsigned int led) ++static int led_get_status(const unsigned int led) + { + int status; + enum led_status_t led_s; +@@ -3877,41 +3877,42 @@ static int led_get_status(unsigned int led) + /* not reached */ + } + +-static int led_set_status(unsigned int led, enum led_status_t ledstatus) ++static int led_set_status(const unsigned int led, ++ const enum led_status_t ledstatus) + { + /* off, on, blink. Index is led_status_t */ +- static const int led_sled_arg1[] = { 0, 1, 3 }; +- static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ +- static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ +- static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; ++ static const unsigned int led_sled_arg1[] = { 0, 1, 3 }; ++ static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 }; + + int rc = 0; + + switch (led_supported) { + case TPACPI_LED_570: +- /* 570 */ +- led = 1 << led; +- if (!acpi_evalf(led_handle, NULL, NULL, "vdd", +- led, led_sled_arg1[ledstatus])) +- rc = -EIO; +- break; ++ /* 570 */ ++ if (led > 7) ++ return -EINVAL; ++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd", ++ (1 << led), led_sled_arg1[ledstatus])) ++ rc = -EIO; ++ break; + case TPACPI_LED_OLD: +- /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ +- led = 1 << led; +- rc = ec_write(TPACPI_LED_EC_HLMS, led); +- if (rc >= 0) +- rc = ec_write(TPACPI_LED_EC_HLBL, +- led * led_exp_hlbl[ledstatus]); +- if (rc >= 0) +- rc = ec_write(TPACPI_LED_EC_HLCL, +- led * led_exp_hlcl[ledstatus]); +- break; ++ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ ++ if (led > 7) ++ return -EINVAL; ++ rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); ++ if (rc >= 0) ++ rc = ec_write(TPACPI_LED_EC_HLBL, ++ (ledstatus == TPACPI_LED_BLINK) << led); ++ if (rc >= 0) ++ rc = ec_write(TPACPI_LED_EC_HLCL, ++ (ledstatus != TPACPI_LED_OFF) << led); ++ break; + case TPACPI_LED_NEW: +- /* all others */ +- if (!acpi_evalf(led_handle, NULL, NULL, "vdd", +- led, led_led_arg1[ledstatus])) +- rc = -EIO; +- break; ++ /* all others */ ++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd", ++ led, led_led_arg1[ledstatus])) ++ rc = -EIO; ++ break; + default: + rc = -ENXIO; + } +-- +1.5.5.3 + -- 2.11.4.GIT