diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 01:42:09 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 01:42:09 -0400 |
commit | 336d63b8a3cadc1c678f4b16d6105633c7f6af75 (patch) | |
tree | d8d713eb39500139ec637c55cc38e62d863d1845 /drivers/platform/x86 | |
parent | 07290bed7968c0e08fb3efe193fb148f1fea5e08 (diff) | |
parent | 0e501834f8c2ba7de2a56e332d346dcf4ac0b593 (diff) |
Merge branch 'thinkpad-acpi' into release
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/Kconfig | 24 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 735 |
2 files changed, 560 insertions, 199 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3608081bc3e0..d45c6ab729f8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -226,6 +226,30 @@ config THINKPAD_ACPI_DEBUG | |||
226 | 226 | ||
227 | If you are not sure, say N here. | 227 | If you are not sure, say N here. |
228 | 228 | ||
229 | config THINKPAD_ACPI_UNSAFE_LEDS | ||
230 | bool "Allow control of important LEDs (unsafe)" | ||
231 | depends on THINKPAD_ACPI | ||
232 | default n | ||
233 | ---help--- | ||
234 | Overriding LED state on ThinkPads can mask important | ||
235 | firmware alerts (like critical battery condition), or misled | ||
236 | the user into damaging the hardware (undocking or ejecting | ||
237 | the bay while buses are still active), etc. | ||
238 | |||
239 | LED control on the ThinkPad is write-only (with very few | ||
240 | exceptions on very ancient models), which makes it | ||
241 | impossible to know beforehand if important information will | ||
242 | be lost when one changes LED state. | ||
243 | |||
244 | Users that know what they are doing can enable this option | ||
245 | and the driver will allow control of every LED, including | ||
246 | the ones on the dock stations. | ||
247 | |||
248 | Never enable this option on a distribution kernel. | ||
249 | |||
250 | Say N here, unless you are building a kernel for your own | ||
251 | use, and need to control the important firmware LEDs. | ||
252 | |||
229 | config THINKPAD_ACPI_DOCK | 253 | config THINKPAD_ACPI_DOCK |
230 | bool "Legacy Docking Station Support" | 254 | bool "Legacy Docking Station Support" |
231 | depends on THINKPAD_ACPI | 255 | depends on THINKPAD_ACPI |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d2433204a40c..ba3682c5cde0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * | 4 | * |
5 | * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net> | 5 | * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net> |
6 | * Copyright (C) 2006-2008 Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 6 | * Copyright (C) 2006-2009 Henrique de Moraes Holschuh <hmh@hmh.eng.br> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define TPACPI_VERSION "0.22" | 24 | #define TPACPI_VERSION "0.22" |
25 | #define TPACPI_SYSFS_VERSION 0x020200 | 25 | #define TPACPI_SYSFS_VERSION 0x020300 |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Changelog: | 28 | * Changelog: |
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/string.h> | 54 | #include <linux/string.h> |
55 | #include <linux/list.h> | 55 | #include <linux/list.h> |
56 | #include <linux/mutex.h> | 56 | #include <linux/mutex.h> |
57 | #include <linux/sched.h> | ||
57 | #include <linux/kthread.h> | 58 | #include <linux/kthread.h> |
58 | #include <linux/freezer.h> | 59 | #include <linux/freezer.h> |
59 | #include <linux/delay.h> | 60 | #include <linux/delay.h> |
@@ -172,29 +173,26 @@ enum { | |||
172 | TPACPI_RFK_UWB_SW_ID, | 173 | TPACPI_RFK_UWB_SW_ID, |
173 | }; | 174 | }; |
174 | 175 | ||
175 | /* Debugging */ | 176 | /* printk headers */ |
176 | #define TPACPI_LOG TPACPI_FILE ": " | 177 | #define TPACPI_LOG TPACPI_FILE ": " |
177 | #define TPACPI_ALERT KERN_ALERT TPACPI_LOG | 178 | #define TPACPI_EMERG KERN_EMERG TPACPI_LOG |
178 | #define TPACPI_CRIT KERN_CRIT TPACPI_LOG | 179 | #define TPACPI_ALERT KERN_ALERT TPACPI_LOG |
179 | #define TPACPI_ERR KERN_ERR TPACPI_LOG | 180 | #define TPACPI_CRIT KERN_CRIT TPACPI_LOG |
180 | #define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG | 181 | #define TPACPI_ERR KERN_ERR TPACPI_LOG |
181 | #define TPACPI_INFO KERN_INFO TPACPI_LOG | 182 | #define TPACPI_WARN KERN_WARNING TPACPI_LOG |
182 | #define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG | 183 | #define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG |
183 | 184 | #define TPACPI_INFO KERN_INFO TPACPI_LOG | |
185 | #define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG | ||
186 | |||
187 | /* Debugging printk groups */ | ||
184 | #define TPACPI_DBG_ALL 0xffff | 188 | #define TPACPI_DBG_ALL 0xffff |
189 | #define TPACPI_DBG_DISCLOSETASK 0x8000 | ||
185 | #define TPACPI_DBG_INIT 0x0001 | 190 | #define TPACPI_DBG_INIT 0x0001 |
186 | #define TPACPI_DBG_EXIT 0x0002 | 191 | #define TPACPI_DBG_EXIT 0x0002 |
187 | #define dbg_printk(a_dbg_level, format, arg...) \ | 192 | #define TPACPI_DBG_RFKILL 0x0004 |
188 | do { if (dbg_level & a_dbg_level) \ | 193 | #define TPACPI_DBG_HKEY 0x0008 |
189 | printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ | 194 | #define TPACPI_DBG_FAN 0x0010 |
190 | } while (0) | 195 | #define TPACPI_DBG_BRGHT 0x0020 |
191 | #ifdef CONFIG_THINKPAD_ACPI_DEBUG | ||
192 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
193 | dbg_printk(a_dbg_level, format, ## arg) | ||
194 | static const char *str_supported(int is_supported); | ||
195 | #else | ||
196 | #define vdbg_printk(a_dbg_level, format, arg...) | ||
197 | #endif | ||
198 | 196 | ||
199 | #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") | 197 | #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") |
200 | #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") | 198 | #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") |
@@ -277,7 +275,6 @@ static struct { | |||
277 | 275 | ||
278 | static struct { | 276 | static struct { |
279 | u16 hotkey_mask_ff:1; | 277 | u16 hotkey_mask_ff:1; |
280 | u16 bright_cmos_ec_unsync:1; | ||
281 | } tp_warned; | 278 | } tp_warned; |
282 | 279 | ||
283 | struct thinkpad_id_data { | 280 | struct thinkpad_id_data { |
@@ -326,6 +323,39 @@ static int tpacpi_uwb_emulstate; | |||
326 | #endif | 323 | #endif |
327 | 324 | ||
328 | 325 | ||
326 | /************************************************************************* | ||
327 | * Debugging helpers | ||
328 | */ | ||
329 | |||
330 | #define dbg_printk(a_dbg_level, format, arg...) \ | ||
331 | do { if (dbg_level & (a_dbg_level)) \ | ||
332 | printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ | ||
333 | } while (0) | ||
334 | |||
335 | #ifdef CONFIG_THINKPAD_ACPI_DEBUG | ||
336 | #define vdbg_printk dbg_printk | ||
337 | static const char *str_supported(int is_supported); | ||
338 | #else | ||
339 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
340 | do { } while (0) | ||
341 | #endif | ||
342 | |||
343 | static void tpacpi_log_usertask(const char * const what) | ||
344 | { | ||
345 | printk(TPACPI_DEBUG "%s: access by process with PID %d\n", | ||
346 | what, task_tgid_vnr(current)); | ||
347 | } | ||
348 | |||
349 | #define tpacpi_disclose_usertask(what, format, arg...) \ | ||
350 | do { \ | ||
351 | if (unlikely( \ | ||
352 | (dbg_level & TPACPI_DBG_DISCLOSETASK) && \ | ||
353 | (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \ | ||
354 | printk(TPACPI_DEBUG "%s: PID %d: " format, \ | ||
355 | what, task_tgid_vnr(current), ## arg); \ | ||
356 | } \ | ||
357 | } while (0) | ||
358 | |||
329 | /**************************************************************************** | 359 | /**************************************************************************** |
330 | **************************************************************************** | 360 | **************************************************************************** |
331 | * | 361 | * |
@@ -989,10 +1019,13 @@ static int __init tpacpi_new_rfkill(const unsigned int id, | |||
989 | /* try to set the initial state as the default for the rfkill | 1019 | /* try to set the initial state as the default for the rfkill |
990 | * type, since we ask the firmware to preserve it across S5 in | 1020 | * type, since we ask the firmware to preserve it across S5 in |
991 | * NVRAM */ | 1021 | * NVRAM */ |
992 | rfkill_set_default(rfktype, | 1022 | if (rfkill_set_default(rfktype, |
993 | (initial_state == RFKILL_STATE_UNBLOCKED) ? | 1023 | (initial_state == RFKILL_STATE_UNBLOCKED) ? |
994 | RFKILL_STATE_UNBLOCKED : | 1024 | RFKILL_STATE_UNBLOCKED : |
995 | RFKILL_STATE_SOFT_BLOCKED); | 1025 | RFKILL_STATE_SOFT_BLOCKED) == -EPERM) |
1026 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
1027 | "Default state for %s cannot be changed\n", | ||
1028 | name); | ||
996 | } | 1029 | } |
997 | 1030 | ||
998 | *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); | 1031 | *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); |
@@ -1020,6 +1053,21 @@ static int __init tpacpi_new_rfkill(const unsigned int id, | |||
1020 | return 0; | 1053 | return 0; |
1021 | } | 1054 | } |
1022 | 1055 | ||
1056 | static void printk_deprecated_attribute(const char * const what, | ||
1057 | const char * const details) | ||
1058 | { | ||
1059 | tpacpi_log_usertask("deprecated sysfs attribute"); | ||
1060 | printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and " | ||
1061 | "will be removed. %s\n", | ||
1062 | what, details); | ||
1063 | } | ||
1064 | |||
1065 | static void printk_deprecated_rfkill_attribute(const char * const what) | ||
1066 | { | ||
1067 | printk_deprecated_attribute(what, | ||
1068 | "Please switch to generic rfkill before year 2010"); | ||
1069 | } | ||
1070 | |||
1023 | /************************************************************************* | 1071 | /************************************************************************* |
1024 | * thinkpad-acpi driver attributes | 1072 | * thinkpad-acpi driver attributes |
1025 | */ | 1073 | */ |
@@ -1382,7 +1430,6 @@ static enum { /* Reasons for waking up */ | |||
1382 | 1430 | ||
1383 | static int hotkey_autosleep_ack; | 1431 | static int hotkey_autosleep_ack; |
1384 | 1432 | ||
1385 | static int hotkey_orig_status; | ||
1386 | static u32 hotkey_orig_mask; | 1433 | static u32 hotkey_orig_mask; |
1387 | static u32 hotkey_all_mask; | 1434 | static u32 hotkey_all_mask; |
1388 | static u32 hotkey_reserved_mask; | 1435 | static u32 hotkey_reserved_mask; |
@@ -1529,9 +1576,9 @@ static int hotkey_status_get(int *status) | |||
1529 | return 0; | 1576 | return 0; |
1530 | } | 1577 | } |
1531 | 1578 | ||
1532 | static int hotkey_status_set(int status) | 1579 | static int hotkey_status_set(bool enable) |
1533 | { | 1580 | { |
1534 | if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status)) | 1581 | if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", enable ? 1 : 0)) |
1535 | return -EIO; | 1582 | return -EIO; |
1536 | 1583 | ||
1537 | return 0; | 1584 | return 0; |
@@ -1847,6 +1894,9 @@ static ssize_t hotkey_enable_show(struct device *dev, | |||
1847 | { | 1894 | { |
1848 | int res, status; | 1895 | int res, status; |
1849 | 1896 | ||
1897 | printk_deprecated_attribute("hotkey_enable", | ||
1898 | "Hotkey reporting is always enabled"); | ||
1899 | |||
1850 | res = hotkey_status_get(&status); | 1900 | res = hotkey_status_get(&status); |
1851 | if (res) | 1901 | if (res) |
1852 | return res; | 1902 | return res; |
@@ -1859,14 +1909,17 @@ static ssize_t hotkey_enable_store(struct device *dev, | |||
1859 | const char *buf, size_t count) | 1909 | const char *buf, size_t count) |
1860 | { | 1910 | { |
1861 | unsigned long t; | 1911 | unsigned long t; |
1862 | int res; | 1912 | |
1913 | printk_deprecated_attribute("hotkey_enable", | ||
1914 | "Hotkeys can be disabled through hotkey_mask"); | ||
1863 | 1915 | ||
1864 | if (parse_strtoul(buf, 1, &t)) | 1916 | if (parse_strtoul(buf, 1, &t)) |
1865 | return -EINVAL; | 1917 | return -EINVAL; |
1866 | 1918 | ||
1867 | res = hotkey_status_set(t); | 1919 | if (t == 0) |
1920 | return -EPERM; | ||
1868 | 1921 | ||
1869 | return (res) ? res : count; | 1922 | return count; |
1870 | } | 1923 | } |
1871 | 1924 | ||
1872 | static struct device_attribute dev_attr_hotkey_enable = | 1925 | static struct device_attribute dev_attr_hotkey_enable = |
@@ -1910,6 +1963,8 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
1910 | 1963 | ||
1911 | mutex_unlock(&hotkey_mutex); | 1964 | mutex_unlock(&hotkey_mutex); |
1912 | 1965 | ||
1966 | tpacpi_disclose_usertask("hotkey_mask", "set to 0x%08lx\n", t); | ||
1967 | |||
1913 | return (res) ? res : count; | 1968 | return (res) ? res : count; |
1914 | } | 1969 | } |
1915 | 1970 | ||
@@ -1922,7 +1977,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev, | |||
1922 | struct device_attribute *attr, | 1977 | struct device_attribute *attr, |
1923 | char *buf) | 1978 | char *buf) |
1924 | { | 1979 | { |
1925 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status); | 1980 | return sprintf(buf, "0\n"); |
1926 | } | 1981 | } |
1927 | 1982 | ||
1928 | static struct device_attribute dev_attr_hotkey_bios_enabled = | 1983 | static struct device_attribute dev_attr_hotkey_bios_enabled = |
@@ -1996,6 +2051,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev, | |||
1996 | 2051 | ||
1997 | mutex_unlock(&hotkey_mutex); | 2052 | mutex_unlock(&hotkey_mutex); |
1998 | 2053 | ||
2054 | tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t); | ||
2055 | |||
1999 | return count; | 2056 | return count; |
2000 | } | 2057 | } |
2001 | 2058 | ||
@@ -2028,6 +2085,8 @@ static ssize_t hotkey_poll_freq_store(struct device *dev, | |||
2028 | hotkey_poll_setup(1); | 2085 | hotkey_poll_setup(1); |
2029 | mutex_unlock(&hotkey_mutex); | 2086 | mutex_unlock(&hotkey_mutex); |
2030 | 2087 | ||
2088 | tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); | ||
2089 | |||
2031 | return count; | 2090 | return count; |
2032 | } | 2091 | } |
2033 | 2092 | ||
@@ -2197,11 +2256,11 @@ static void hotkey_exit(void) | |||
2197 | kfree(hotkey_keycode_map); | 2256 | kfree(hotkey_keycode_map); |
2198 | 2257 | ||
2199 | if (tp_features.hotkey) { | 2258 | if (tp_features.hotkey) { |
2200 | dbg_printk(TPACPI_DBG_EXIT, | 2259 | dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY, |
2201 | "restoring original hot key mask\n"); | 2260 | "restoring original hot key mask\n"); |
2202 | /* no short-circuit boolean operator below! */ | 2261 | /* no short-circuit boolean operator below! */ |
2203 | if ((hotkey_mask_set(hotkey_orig_mask) | | 2262 | if ((hotkey_mask_set(hotkey_orig_mask) | |
2204 | hotkey_status_set(hotkey_orig_status)) != 0) | 2263 | hotkey_status_set(false)) != 0) |
2205 | printk(TPACPI_ERR | 2264 | printk(TPACPI_ERR |
2206 | "failed to restore hot key mask " | 2265 | "failed to restore hot key mask " |
2207 | "to BIOS defaults\n"); | 2266 | "to BIOS defaults\n"); |
@@ -2327,7 +2386,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2327 | int status; | 2386 | int status; |
2328 | int hkeyv; | 2387 | int hkeyv; |
2329 | 2388 | ||
2330 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); | 2389 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2390 | "initializing hotkey subdriver\n"); | ||
2331 | 2391 | ||
2332 | BUG_ON(!tpacpi_inputdev); | 2392 | BUG_ON(!tpacpi_inputdev); |
2333 | BUG_ON(tpacpi_inputdev->open != NULL || | 2393 | BUG_ON(tpacpi_inputdev->open != NULL || |
@@ -2344,7 +2404,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2344 | /* hotkey not supported on 570 */ | 2404 | /* hotkey not supported on 570 */ |
2345 | tp_features.hotkey = hkey_handle != NULL; | 2405 | tp_features.hotkey = hkey_handle != NULL; |
2346 | 2406 | ||
2347 | vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", | 2407 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2408 | "hotkeys are %s\n", | ||
2348 | str_supported(tp_features.hotkey)); | 2409 | str_supported(tp_features.hotkey)); |
2349 | 2410 | ||
2350 | if (!tp_features.hotkey) | 2411 | if (!tp_features.hotkey) |
@@ -2376,10 +2437,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2376 | * T4x, X31, and later | 2437 | * T4x, X31, and later |
2377 | */ | 2438 | */ |
2378 | tp_features.hotkey_mask = 1; | 2439 | tp_features.hotkey_mask = 1; |
2440 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | ||
2441 | "firmware HKEY interface version: 0x%x\n", | ||
2442 | hkeyv); | ||
2379 | } | 2443 | } |
2380 | } | 2444 | } |
2381 | 2445 | ||
2382 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", | 2446 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2447 | "hotkey masks are %s\n", | ||
2383 | str_supported(tp_features.hotkey_mask)); | 2448 | str_supported(tp_features.hotkey_mask)); |
2384 | 2449 | ||
2385 | if (tp_features.hotkey_mask) { | 2450 | if (tp_features.hotkey_mask) { |
@@ -2396,10 +2461,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2396 | 2461 | ||
2397 | /* hotkey_source_mask *must* be zero for | 2462 | /* hotkey_source_mask *must* be zero for |
2398 | * the first hotkey_mask_get */ | 2463 | * the first hotkey_mask_get */ |
2399 | res = hotkey_status_get(&hotkey_orig_status); | ||
2400 | if (res) | ||
2401 | goto err_exit; | ||
2402 | |||
2403 | if (tp_features.hotkey_mask) { | 2464 | if (tp_features.hotkey_mask) { |
2404 | res = hotkey_mask_get(); | 2465 | res = hotkey_mask_get(); |
2405 | if (res) | 2466 | if (res) |
@@ -2422,7 +2483,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2422 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; | 2483 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; |
2423 | } | 2484 | } |
2424 | 2485 | ||
2425 | vdbg_printk(TPACPI_DBG_INIT, | 2486 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2426 | "hotkey source mask 0x%08x, polling freq %d\n", | 2487 | "hotkey source mask 0x%08x, polling freq %d\n", |
2427 | hotkey_source_mask, hotkey_poll_freq); | 2488 | hotkey_source_mask, hotkey_poll_freq); |
2428 | #endif | 2489 | #endif |
@@ -2476,12 +2537,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2476 | } | 2537 | } |
2477 | 2538 | ||
2478 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | 2539 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { |
2479 | dbg_printk(TPACPI_DBG_INIT, | 2540 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2480 | "using Lenovo default hot key map\n"); | 2541 | "using Lenovo default hot key map\n"); |
2481 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, | 2542 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, |
2482 | TPACPI_HOTKEY_MAP_SIZE); | 2543 | TPACPI_HOTKEY_MAP_SIZE); |
2483 | } else { | 2544 | } else { |
2484 | dbg_printk(TPACPI_DBG_INIT, | 2545 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2485 | "using IBM default hot key map\n"); | 2546 | "using IBM default hot key map\n"); |
2486 | memcpy(hotkey_keycode_map, &ibm_keycode_map, | 2547 | memcpy(hotkey_keycode_map, &ibm_keycode_map, |
2487 | TPACPI_HOTKEY_MAP_SIZE); | 2548 | TPACPI_HOTKEY_MAP_SIZE); |
@@ -2538,8 +2599,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2538 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); | 2599 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); |
2539 | } | 2600 | } |
2540 | 2601 | ||
2541 | dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); | 2602 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2542 | res = hotkey_status_set(1); | 2603 | "enabling firmware HKEY event interface...\n"); |
2604 | res = hotkey_status_set(true); | ||
2543 | if (res) { | 2605 | if (res) { |
2544 | hotkey_exit(); | 2606 | hotkey_exit(); |
2545 | return res; | 2607 | return res; |
@@ -2552,8 +2614,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2552 | return res; | 2614 | return res; |
2553 | } | 2615 | } |
2554 | 2616 | ||
2555 | dbg_printk(TPACPI_DBG_INIT, | 2617 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
2556 | "legacy hot key reporting over procfs %s\n", | 2618 | "legacy ibm/hotkey event reporting over procfs %s\n", |
2557 | (hotkey_report_mode < 2) ? | 2619 | (hotkey_report_mode < 2) ? |
2558 | "enabled" : "disabled"); | 2620 | "enabled" : "disabled"); |
2559 | 2621 | ||
@@ -2884,9 +2946,17 @@ static int hotkey_read(char *p) | |||
2884 | return len; | 2946 | return len; |
2885 | } | 2947 | } |
2886 | 2948 | ||
2949 | static void hotkey_enabledisable_warn(void) | ||
2950 | { | ||
2951 | tpacpi_log_usertask("procfs hotkey enable/disable"); | ||
2952 | WARN(1, TPACPI_WARN | ||
2953 | "hotkey enable/disable functionality has been " | ||
2954 | "removed from the driver. Hotkeys are always enabled.\n"); | ||
2955 | } | ||
2956 | |||
2887 | static int hotkey_write(char *buf) | 2957 | static int hotkey_write(char *buf) |
2888 | { | 2958 | { |
2889 | int res, status; | 2959 | int res; |
2890 | u32 mask; | 2960 | u32 mask; |
2891 | char *cmd; | 2961 | char *cmd; |
2892 | 2962 | ||
@@ -2896,17 +2966,16 @@ static int hotkey_write(char *buf) | |||
2896 | if (mutex_lock_killable(&hotkey_mutex)) | 2966 | if (mutex_lock_killable(&hotkey_mutex)) |
2897 | return -ERESTARTSYS; | 2967 | return -ERESTARTSYS; |
2898 | 2968 | ||
2899 | status = -1; | ||
2900 | mask = hotkey_mask; | 2969 | mask = hotkey_mask; |
2901 | 2970 | ||
2902 | res = 0; | 2971 | res = 0; |
2903 | while ((cmd = next_cmd(&buf))) { | 2972 | while ((cmd = next_cmd(&buf))) { |
2904 | if (strlencmp(cmd, "enable") == 0) { | 2973 | if (strlencmp(cmd, "enable") == 0) { |
2905 | status = 1; | 2974 | hotkey_enabledisable_warn(); |
2906 | } else if (strlencmp(cmd, "disable") == 0) { | 2975 | } else if (strlencmp(cmd, "disable") == 0) { |
2907 | status = 0; | 2976 | hotkey_enabledisable_warn(); |
2977 | res = -EPERM; | ||
2908 | } else if (strlencmp(cmd, "reset") == 0) { | 2978 | } else if (strlencmp(cmd, "reset") == 0) { |
2909 | status = hotkey_orig_status; | ||
2910 | mask = hotkey_orig_mask; | 2979 | mask = hotkey_orig_mask; |
2911 | } else if (sscanf(cmd, "0x%x", &mask) == 1) { | 2980 | } else if (sscanf(cmd, "0x%x", &mask) == 1) { |
2912 | /* mask set */ | 2981 | /* mask set */ |
@@ -2917,8 +2986,10 @@ static int hotkey_write(char *buf) | |||
2917 | goto errexit; | 2986 | goto errexit; |
2918 | } | 2987 | } |
2919 | } | 2988 | } |
2920 | if (status != -1) | 2989 | |
2921 | res = hotkey_status_set(status); | 2990 | if (!res) |
2991 | tpacpi_disclose_usertask("procfs hotkey", | ||
2992 | "set mask to 0x%08x\n", mask); | ||
2922 | 2993 | ||
2923 | if (!res && mask != hotkey_mask) | 2994 | if (!res && mask != hotkey_mask) |
2924 | res = hotkey_mask_set(mask); | 2995 | res = hotkey_mask_set(mask); |
@@ -2971,13 +3042,17 @@ enum { | |||
2971 | TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */ | 3042 | TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */ |
2972 | }; | 3043 | }; |
2973 | 3044 | ||
3045 | #define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" | ||
3046 | |||
2974 | static struct rfkill *tpacpi_bluetooth_rfkill; | 3047 | static struct rfkill *tpacpi_bluetooth_rfkill; |
2975 | 3048 | ||
2976 | static void bluetooth_suspend(pm_message_t state) | 3049 | static void bluetooth_suspend(pm_message_t state) |
2977 | { | 3050 | { |
2978 | /* Try to make sure radio will resume powered off */ | 3051 | /* Try to make sure radio will resume powered off */ |
2979 | acpi_evalf(NULL, NULL, "\\BLTH", "vd", | 3052 | if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", |
2980 | TP_ACPI_BLTH_PWR_OFF_ON_RESUME); | 3053 | TP_ACPI_BLTH_PWR_OFF_ON_RESUME)) |
3054 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3055 | "bluetooth power down on resume request failed\n"); | ||
2981 | } | 3056 | } |
2982 | 3057 | ||
2983 | static int bluetooth_get_radiosw(void) | 3058 | static int bluetooth_get_radiosw(void) |
@@ -3015,6 +3090,10 @@ static void bluetooth_update_rfk(void) | |||
3015 | if (status < 0) | 3090 | if (status < 0) |
3016 | return; | 3091 | return; |
3017 | rfkill_force_state(tpacpi_bluetooth_rfkill, status); | 3092 | rfkill_force_state(tpacpi_bluetooth_rfkill, status); |
3093 | |||
3094 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3095 | "forced rfkill state to %d\n", | ||
3096 | status); | ||
3018 | } | 3097 | } |
3019 | 3098 | ||
3020 | static int bluetooth_set_radiosw(int radio_on, int update_rfk) | 3099 | static int bluetooth_set_radiosw(int radio_on, int update_rfk) |
@@ -3030,6 +3109,9 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk) | |||
3030 | && radio_on) | 3109 | && radio_on) |
3031 | return -EPERM; | 3110 | return -EPERM; |
3032 | 3111 | ||
3112 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3113 | "will %s bluetooth\n", radio_on ? "enable" : "disable"); | ||
3114 | |||
3033 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | 3115 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES |
3034 | if (dbg_bluetoothemul) { | 3116 | if (dbg_bluetoothemul) { |
3035 | tpacpi_bluetooth_emulstate = !!radio_on; | 3117 | tpacpi_bluetooth_emulstate = !!radio_on; |
@@ -3060,6 +3142,8 @@ static ssize_t bluetooth_enable_show(struct device *dev, | |||
3060 | { | 3142 | { |
3061 | int status; | 3143 | int status; |
3062 | 3144 | ||
3145 | printk_deprecated_rfkill_attribute("bluetooth_enable"); | ||
3146 | |||
3063 | status = bluetooth_get_radiosw(); | 3147 | status = bluetooth_get_radiosw(); |
3064 | if (status < 0) | 3148 | if (status < 0) |
3065 | return status; | 3149 | return status; |
@@ -3075,9 +3159,13 @@ static ssize_t bluetooth_enable_store(struct device *dev, | |||
3075 | unsigned long t; | 3159 | unsigned long t; |
3076 | int res; | 3160 | int res; |
3077 | 3161 | ||
3162 | printk_deprecated_rfkill_attribute("bluetooth_enable"); | ||
3163 | |||
3078 | if (parse_strtoul(buf, 1, &t)) | 3164 | if (parse_strtoul(buf, 1, &t)) |
3079 | return -EINVAL; | 3165 | return -EINVAL; |
3080 | 3166 | ||
3167 | tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t); | ||
3168 | |||
3081 | res = bluetooth_set_radiosw(t, 1); | 3169 | res = bluetooth_set_radiosw(t, 1); |
3082 | 3170 | ||
3083 | return (res) ? res : count; | 3171 | return (res) ? res : count; |
@@ -3111,6 +3199,8 @@ static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state) | |||
3111 | 3199 | ||
3112 | static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) | 3200 | static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) |
3113 | { | 3201 | { |
3202 | dbg_printk(TPACPI_DBG_RFKILL, | ||
3203 | "request to change radio state to %d\n", state); | ||
3114 | return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); | 3204 | return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); |
3115 | } | 3205 | } |
3116 | 3206 | ||
@@ -3121,6 +3211,9 @@ static void bluetooth_shutdown(void) | |||
3121 | TP_ACPI_BLTH_SAVE_STATE)) | 3211 | TP_ACPI_BLTH_SAVE_STATE)) |
3122 | printk(TPACPI_NOTICE | 3212 | printk(TPACPI_NOTICE |
3123 | "failed to save bluetooth state to NVRAM\n"); | 3213 | "failed to save bluetooth state to NVRAM\n"); |
3214 | else | ||
3215 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3216 | "bluestooth state saved to NVRAM\n"); | ||
3124 | } | 3217 | } |
3125 | 3218 | ||
3126 | static void bluetooth_exit(void) | 3219 | static void bluetooth_exit(void) |
@@ -3139,7 +3232,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
3139 | int res; | 3232 | int res; |
3140 | int status = 0; | 3233 | int status = 0; |
3141 | 3234 | ||
3142 | vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); | 3235 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3236 | "initializing bluetooth subdriver\n"); | ||
3143 | 3237 | ||
3144 | TPACPI_ACPIHANDLE_INIT(hkey); | 3238 | TPACPI_ACPIHANDLE_INIT(hkey); |
3145 | 3239 | ||
@@ -3148,7 +3242,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
3148 | tp_features.bluetooth = hkey_handle && | 3242 | tp_features.bluetooth = hkey_handle && |
3149 | acpi_evalf(hkey_handle, &status, "GBDC", "qd"); | 3243 | acpi_evalf(hkey_handle, &status, "GBDC", "qd"); |
3150 | 3244 | ||
3151 | vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n", | 3245 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3246 | "bluetooth is %s, status 0x%02x\n", | ||
3152 | str_supported(tp_features.bluetooth), | 3247 | str_supported(tp_features.bluetooth), |
3153 | status); | 3248 | status); |
3154 | 3249 | ||
@@ -3163,7 +3258,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
3163 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { | 3258 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { |
3164 | /* no bluetooth hardware present in system */ | 3259 | /* no bluetooth hardware present in system */ |
3165 | tp_features.bluetooth = 0; | 3260 | tp_features.bluetooth = 0; |
3166 | dbg_printk(TPACPI_DBG_INIT, | 3261 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3167 | "bluetooth hardware not installed\n"); | 3262 | "bluetooth hardware not installed\n"); |
3168 | } | 3263 | } |
3169 | 3264 | ||
@@ -3178,7 +3273,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
3178 | res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, | 3273 | res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, |
3179 | &tpacpi_bluetooth_rfkill, | 3274 | &tpacpi_bluetooth_rfkill, |
3180 | RFKILL_TYPE_BLUETOOTH, | 3275 | RFKILL_TYPE_BLUETOOTH, |
3181 | "tpacpi_bluetooth_sw", | 3276 | TPACPI_RFK_BLUETOOTH_SW_NAME, |
3182 | true, | 3277 | true, |
3183 | tpacpi_bluetooth_rfk_set, | 3278 | tpacpi_bluetooth_rfk_set, |
3184 | tpacpi_bluetooth_rfk_get); | 3279 | tpacpi_bluetooth_rfk_get); |
@@ -3211,19 +3306,27 @@ static int bluetooth_read(char *p) | |||
3211 | static int bluetooth_write(char *buf) | 3306 | static int bluetooth_write(char *buf) |
3212 | { | 3307 | { |
3213 | char *cmd; | 3308 | char *cmd; |
3309 | int state = -1; | ||
3214 | 3310 | ||
3215 | if (!tp_features.bluetooth) | 3311 | if (!tp_features.bluetooth) |
3216 | return -ENODEV; | 3312 | return -ENODEV; |
3217 | 3313 | ||
3218 | while ((cmd = next_cmd(&buf))) { | 3314 | while ((cmd = next_cmd(&buf))) { |
3219 | if (strlencmp(cmd, "enable") == 0) { | 3315 | if (strlencmp(cmd, "enable") == 0) { |
3220 | bluetooth_set_radiosw(1, 1); | 3316 | state = 1; |
3221 | } else if (strlencmp(cmd, "disable") == 0) { | 3317 | } else if (strlencmp(cmd, "disable") == 0) { |
3222 | bluetooth_set_radiosw(0, 1); | 3318 | state = 0; |
3223 | } else | 3319 | } else |
3224 | return -EINVAL; | 3320 | return -EINVAL; |
3225 | } | 3321 | } |
3226 | 3322 | ||
3323 | if (state != -1) { | ||
3324 | tpacpi_disclose_usertask("procfs bluetooth", | ||
3325 | "attempt to %s\n", | ||
3326 | state ? "enable" : "disable"); | ||
3327 | bluetooth_set_radiosw(state, 1); | ||
3328 | } | ||
3329 | |||
3227 | return 0; | 3330 | return 0; |
3228 | } | 3331 | } |
3229 | 3332 | ||
@@ -3248,13 +3351,17 @@ enum { | |||
3248 | off / last state */ | 3351 | off / last state */ |
3249 | }; | 3352 | }; |
3250 | 3353 | ||
3354 | #define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" | ||
3355 | |||
3251 | static struct rfkill *tpacpi_wan_rfkill; | 3356 | static struct rfkill *tpacpi_wan_rfkill; |
3252 | 3357 | ||
3253 | static void wan_suspend(pm_message_t state) | 3358 | static void wan_suspend(pm_message_t state) |
3254 | { | 3359 | { |
3255 | /* Try to make sure radio will resume powered off */ | 3360 | /* Try to make sure radio will resume powered off */ |
3256 | acpi_evalf(NULL, NULL, "\\WGSV", "qvd", | 3361 | if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd", |
3257 | TP_ACPI_WGSV_PWR_OFF_ON_RESUME); | 3362 | TP_ACPI_WGSV_PWR_OFF_ON_RESUME)) |
3363 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3364 | "WWAN power down on resume request failed\n"); | ||
3258 | } | 3365 | } |
3259 | 3366 | ||
3260 | static int wan_get_radiosw(void) | 3367 | static int wan_get_radiosw(void) |
@@ -3292,6 +3399,10 @@ static void wan_update_rfk(void) | |||
3292 | if (status < 0) | 3399 | if (status < 0) |
3293 | return; | 3400 | return; |
3294 | rfkill_force_state(tpacpi_wan_rfkill, status); | 3401 | rfkill_force_state(tpacpi_wan_rfkill, status); |
3402 | |||
3403 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3404 | "forced rfkill state to %d\n", | ||
3405 | status); | ||
3295 | } | 3406 | } |
3296 | 3407 | ||
3297 | static int wan_set_radiosw(int radio_on, int update_rfk) | 3408 | static int wan_set_radiosw(int radio_on, int update_rfk) |
@@ -3307,6 +3418,9 @@ static int wan_set_radiosw(int radio_on, int update_rfk) | |||
3307 | && radio_on) | 3418 | && radio_on) |
3308 | return -EPERM; | 3419 | return -EPERM; |
3309 | 3420 | ||
3421 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3422 | "will %s WWAN\n", radio_on ? "enable" : "disable"); | ||
3423 | |||
3310 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | 3424 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES |
3311 | if (dbg_wwanemul) { | 3425 | if (dbg_wwanemul) { |
3312 | tpacpi_wwan_emulstate = !!radio_on; | 3426 | tpacpi_wwan_emulstate = !!radio_on; |
@@ -3337,6 +3451,8 @@ static ssize_t wan_enable_show(struct device *dev, | |||
3337 | { | 3451 | { |
3338 | int status; | 3452 | int status; |
3339 | 3453 | ||
3454 | printk_deprecated_rfkill_attribute("wwan_enable"); | ||
3455 | |||
3340 | status = wan_get_radiosw(); | 3456 | status = wan_get_radiosw(); |
3341 | if (status < 0) | 3457 | if (status < 0) |
3342 | return status; | 3458 | return status; |
@@ -3352,9 +3468,13 @@ static ssize_t wan_enable_store(struct device *dev, | |||
3352 | unsigned long t; | 3468 | unsigned long t; |
3353 | int res; | 3469 | int res; |
3354 | 3470 | ||
3471 | printk_deprecated_rfkill_attribute("wwan_enable"); | ||
3472 | |||
3355 | if (parse_strtoul(buf, 1, &t)) | 3473 | if (parse_strtoul(buf, 1, &t)) |
3356 | return -EINVAL; | 3474 | return -EINVAL; |
3357 | 3475 | ||
3476 | tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t); | ||
3477 | |||
3358 | res = wan_set_radiosw(t, 1); | 3478 | res = wan_set_radiosw(t, 1); |
3359 | 3479 | ||
3360 | return (res) ? res : count; | 3480 | return (res) ? res : count; |
@@ -3388,6 +3508,8 @@ static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state) | |||
3388 | 3508 | ||
3389 | static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) | 3509 | static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) |
3390 | { | 3510 | { |
3511 | dbg_printk(TPACPI_DBG_RFKILL, | ||
3512 | "request to change radio state to %d\n", state); | ||
3391 | return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); | 3513 | return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); |
3392 | } | 3514 | } |
3393 | 3515 | ||
@@ -3398,6 +3520,9 @@ static void wan_shutdown(void) | |||
3398 | TP_ACPI_WGSV_SAVE_STATE)) | 3520 | TP_ACPI_WGSV_SAVE_STATE)) |
3399 | printk(TPACPI_NOTICE | 3521 | printk(TPACPI_NOTICE |
3400 | "failed to save WWAN state to NVRAM\n"); | 3522 | "failed to save WWAN state to NVRAM\n"); |
3523 | else | ||
3524 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3525 | "WWAN state saved to NVRAM\n"); | ||
3401 | } | 3526 | } |
3402 | 3527 | ||
3403 | static void wan_exit(void) | 3528 | static void wan_exit(void) |
@@ -3416,14 +3541,16 @@ static int __init wan_init(struct ibm_init_struct *iibm) | |||
3416 | int res; | 3541 | int res; |
3417 | int status = 0; | 3542 | int status = 0; |
3418 | 3543 | ||
3419 | vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); | 3544 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3545 | "initializing wan subdriver\n"); | ||
3420 | 3546 | ||
3421 | TPACPI_ACPIHANDLE_INIT(hkey); | 3547 | TPACPI_ACPIHANDLE_INIT(hkey); |
3422 | 3548 | ||
3423 | tp_features.wan = hkey_handle && | 3549 | tp_features.wan = hkey_handle && |
3424 | acpi_evalf(hkey_handle, &status, "GWAN", "qd"); | 3550 | acpi_evalf(hkey_handle, &status, "GWAN", "qd"); |
3425 | 3551 | ||
3426 | vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n", | 3552 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3553 | "wan is %s, status 0x%02x\n", | ||
3427 | str_supported(tp_features.wan), | 3554 | str_supported(tp_features.wan), |
3428 | status); | 3555 | status); |
3429 | 3556 | ||
@@ -3438,7 +3565,7 @@ static int __init wan_init(struct ibm_init_struct *iibm) | |||
3438 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { | 3565 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { |
3439 | /* no wan hardware present in system */ | 3566 | /* no wan hardware present in system */ |
3440 | tp_features.wan = 0; | 3567 | tp_features.wan = 0; |
3441 | dbg_printk(TPACPI_DBG_INIT, | 3568 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3442 | "wan hardware not installed\n"); | 3569 | "wan hardware not installed\n"); |
3443 | } | 3570 | } |
3444 | 3571 | ||
@@ -3453,7 +3580,7 @@ static int __init wan_init(struct ibm_init_struct *iibm) | |||
3453 | res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, | 3580 | res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, |
3454 | &tpacpi_wan_rfkill, | 3581 | &tpacpi_wan_rfkill, |
3455 | RFKILL_TYPE_WWAN, | 3582 | RFKILL_TYPE_WWAN, |
3456 | "tpacpi_wwan_sw", | 3583 | TPACPI_RFK_WWAN_SW_NAME, |
3457 | true, | 3584 | true, |
3458 | tpacpi_wan_rfk_set, | 3585 | tpacpi_wan_rfk_set, |
3459 | tpacpi_wan_rfk_get); | 3586 | tpacpi_wan_rfk_get); |
@@ -3471,6 +3598,8 @@ static int wan_read(char *p) | |||
3471 | int len = 0; | 3598 | int len = 0; |
3472 | int status = wan_get_radiosw(); | 3599 | int status = wan_get_radiosw(); |
3473 | 3600 | ||
3601 | tpacpi_disclose_usertask("procfs wan", "read"); | ||
3602 | |||
3474 | if (!tp_features.wan) | 3603 | if (!tp_features.wan) |
3475 | len += sprintf(p + len, "status:\t\tnot supported\n"); | 3604 | len += sprintf(p + len, "status:\t\tnot supported\n"); |
3476 | else { | 3605 | else { |
@@ -3486,19 +3615,27 @@ static int wan_read(char *p) | |||
3486 | static int wan_write(char *buf) | 3615 | static int wan_write(char *buf) |
3487 | { | 3616 | { |
3488 | char *cmd; | 3617 | char *cmd; |
3618 | int state = -1; | ||
3489 | 3619 | ||
3490 | if (!tp_features.wan) | 3620 | if (!tp_features.wan) |
3491 | return -ENODEV; | 3621 | return -ENODEV; |
3492 | 3622 | ||
3493 | while ((cmd = next_cmd(&buf))) { | 3623 | while ((cmd = next_cmd(&buf))) { |
3494 | if (strlencmp(cmd, "enable") == 0) { | 3624 | if (strlencmp(cmd, "enable") == 0) { |
3495 | wan_set_radiosw(1, 1); | 3625 | state = 1; |
3496 | } else if (strlencmp(cmd, "disable") == 0) { | 3626 | } else if (strlencmp(cmd, "disable") == 0) { |
3497 | wan_set_radiosw(0, 1); | 3627 | state = 0; |
3498 | } else | 3628 | } else |
3499 | return -EINVAL; | 3629 | return -EINVAL; |
3500 | } | 3630 | } |
3501 | 3631 | ||
3632 | if (state != -1) { | ||
3633 | tpacpi_disclose_usertask("procfs wan", | ||
3634 | "attempt to %s\n", | ||
3635 | state ? "enable" : "disable"); | ||
3636 | wan_set_radiosw(state, 1); | ||
3637 | } | ||
3638 | |||
3502 | return 0; | 3639 | return 0; |
3503 | } | 3640 | } |
3504 | 3641 | ||
@@ -3521,6 +3658,8 @@ enum { | |||
3521 | TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */ | 3658 | TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */ |
3522 | }; | 3659 | }; |
3523 | 3660 | ||
3661 | #define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw" | ||
3662 | |||
3524 | static struct rfkill *tpacpi_uwb_rfkill; | 3663 | static struct rfkill *tpacpi_uwb_rfkill; |
3525 | 3664 | ||
3526 | static int uwb_get_radiosw(void) | 3665 | static int uwb_get_radiosw(void) |
@@ -3558,6 +3697,10 @@ static void uwb_update_rfk(void) | |||
3558 | if (status < 0) | 3697 | if (status < 0) |
3559 | return; | 3698 | return; |
3560 | rfkill_force_state(tpacpi_uwb_rfkill, status); | 3699 | rfkill_force_state(tpacpi_uwb_rfkill, status); |
3700 | |||
3701 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3702 | "forced rfkill state to %d\n", | ||
3703 | status); | ||
3561 | } | 3704 | } |
3562 | 3705 | ||
3563 | static int uwb_set_radiosw(int radio_on, int update_rfk) | 3706 | static int uwb_set_radiosw(int radio_on, int update_rfk) |
@@ -3573,6 +3716,9 @@ static int uwb_set_radiosw(int radio_on, int update_rfk) | |||
3573 | && radio_on) | 3716 | && radio_on) |
3574 | return -EPERM; | 3717 | return -EPERM; |
3575 | 3718 | ||
3719 | vdbg_printk(TPACPI_DBG_RFKILL, | ||
3720 | "will %s UWB\n", radio_on ? "enable" : "disable"); | ||
3721 | |||
3576 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | 3722 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES |
3577 | if (dbg_uwbemul) { | 3723 | if (dbg_uwbemul) { |
3578 | tpacpi_uwb_emulstate = !!radio_on; | 3724 | tpacpi_uwb_emulstate = !!radio_on; |
@@ -3607,6 +3753,8 @@ static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state) | |||
3607 | 3753 | ||
3608 | static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state) | 3754 | static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state) |
3609 | { | 3755 | { |
3756 | dbg_printk(TPACPI_DBG_RFKILL, | ||
3757 | "request to change radio state to %d\n", state); | ||
3610 | return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); | 3758 | return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); |
3611 | } | 3759 | } |
3612 | 3760 | ||
@@ -3621,14 +3769,16 @@ static int __init uwb_init(struct ibm_init_struct *iibm) | |||
3621 | int res; | 3769 | int res; |
3622 | int status = 0; | 3770 | int status = 0; |
3623 | 3771 | ||
3624 | vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n"); | 3772 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3773 | "initializing uwb subdriver\n"); | ||
3625 | 3774 | ||
3626 | TPACPI_ACPIHANDLE_INIT(hkey); | 3775 | TPACPI_ACPIHANDLE_INIT(hkey); |
3627 | 3776 | ||
3628 | tp_features.uwb = hkey_handle && | 3777 | tp_features.uwb = hkey_handle && |
3629 | acpi_evalf(hkey_handle, &status, "GUWB", "qd"); | 3778 | acpi_evalf(hkey_handle, &status, "GUWB", "qd"); |
3630 | 3779 | ||
3631 | vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n", | 3780 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
3781 | "uwb is %s, status 0x%02x\n", | ||
3632 | str_supported(tp_features.uwb), | 3782 | str_supported(tp_features.uwb), |
3633 | status); | 3783 | status); |
3634 | 3784 | ||
@@ -3653,7 +3803,7 @@ static int __init uwb_init(struct ibm_init_struct *iibm) | |||
3653 | res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, | 3803 | res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, |
3654 | &tpacpi_uwb_rfkill, | 3804 | &tpacpi_uwb_rfkill, |
3655 | RFKILL_TYPE_UWB, | 3805 | RFKILL_TYPE_UWB, |
3656 | "tpacpi_uwb_sw", | 3806 | TPACPI_RFK_UWB_SW_NAME, |
3657 | false, | 3807 | false, |
3658 | tpacpi_uwb_rfk_set, | 3808 | tpacpi_uwb_rfk_set, |
3659 | tpacpi_uwb_rfk_get); | 3809 | tpacpi_uwb_rfk_get); |
@@ -4602,6 +4752,16 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | |||
4602 | "tpacpi::unknown_led", | 4752 | "tpacpi::unknown_led", |
4603 | "tpacpi::standby", | 4753 | "tpacpi::standby", |
4604 | }; | 4754 | }; |
4755 | #define TPACPI_SAFE_LEDS 0x0081U | ||
4756 | |||
4757 | static inline bool tpacpi_is_led_restricted(const unsigned int led) | ||
4758 | { | ||
4759 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | ||
4760 | return false; | ||
4761 | #else | ||
4762 | return (TPACPI_SAFE_LEDS & (1 << led)) == 0; | ||
4763 | #endif | ||
4764 | } | ||
4605 | 4765 | ||
4606 | static int led_get_status(const unsigned int led) | 4766 | static int led_get_status(const unsigned int led) |
4607 | { | 4767 | { |
@@ -4639,16 +4799,20 @@ static int led_set_status(const unsigned int led, | |||
4639 | switch (led_supported) { | 4799 | switch (led_supported) { |
4640 | case TPACPI_LED_570: | 4800 | case TPACPI_LED_570: |
4641 | /* 570 */ | 4801 | /* 570 */ |
4642 | if (led > 7) | 4802 | if (unlikely(led > 7)) |
4643 | return -EINVAL; | 4803 | return -EINVAL; |
4804 | if (unlikely(tpacpi_is_led_restricted(led))) | ||
4805 | return -EPERM; | ||
4644 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | 4806 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", |
4645 | (1 << led), led_sled_arg1[ledstatus])) | 4807 | (1 << led), led_sled_arg1[ledstatus])) |
4646 | rc = -EIO; | 4808 | rc = -EIO; |
4647 | break; | 4809 | break; |
4648 | case TPACPI_LED_OLD: | 4810 | case TPACPI_LED_OLD: |
4649 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ | 4811 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ |
4650 | if (led > 7) | 4812 | if (unlikely(led > 7)) |
4651 | return -EINVAL; | 4813 | return -EINVAL; |
4814 | if (unlikely(tpacpi_is_led_restricted(led))) | ||
4815 | return -EPERM; | ||
4652 | rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); | 4816 | rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); |
4653 | if (rc >= 0) | 4817 | if (rc >= 0) |
4654 | rc = ec_write(TPACPI_LED_EC_HLBL, | 4818 | rc = ec_write(TPACPI_LED_EC_HLBL, |
@@ -4659,6 +4823,10 @@ static int led_set_status(const unsigned int led, | |||
4659 | break; | 4823 | break; |
4660 | case TPACPI_LED_NEW: | 4824 | case TPACPI_LED_NEW: |
4661 | /* all others */ | 4825 | /* all others */ |
4826 | if (unlikely(led >= TPACPI_LED_NUMLEDS)) | ||
4827 | return -EINVAL; | ||
4828 | if (unlikely(tpacpi_is_led_restricted(led))) | ||
4829 | return -EPERM; | ||
4662 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | 4830 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", |
4663 | led, led_led_arg1[ledstatus])) | 4831 | led, led_led_arg1[ledstatus])) |
4664 | rc = -EIO; | 4832 | rc = -EIO; |
@@ -4751,6 +4919,30 @@ static void led_exit(void) | |||
4751 | kfree(tpacpi_leds); | 4919 | kfree(tpacpi_leds); |
4752 | } | 4920 | } |
4753 | 4921 | ||
4922 | static int __init tpacpi_init_led(unsigned int led) | ||
4923 | { | ||
4924 | int rc; | ||
4925 | |||
4926 | tpacpi_leds[led].led = led; | ||
4927 | |||
4928 | tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; | ||
4929 | tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; | ||
4930 | if (led_supported == TPACPI_LED_570) | ||
4931 | tpacpi_leds[led].led_classdev.brightness_get = | ||
4932 | &led_sysfs_get; | ||
4933 | |||
4934 | tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led]; | ||
4935 | |||
4936 | INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker); | ||
4937 | |||
4938 | rc = led_classdev_register(&tpacpi_pdev->dev, | ||
4939 | &tpacpi_leds[led].led_classdev); | ||
4940 | if (rc < 0) | ||
4941 | tpacpi_leds[led].led_classdev.name = NULL; | ||
4942 | |||
4943 | return rc; | ||
4944 | } | ||
4945 | |||
4754 | static int __init led_init(struct ibm_init_struct *iibm) | 4946 | static int __init led_init(struct ibm_init_struct *iibm) |
4755 | { | 4947 | { |
4756 | unsigned int i; | 4948 | unsigned int i; |
@@ -4784,27 +4976,21 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
4784 | } | 4976 | } |
4785 | 4977 | ||
4786 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { | 4978 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { |
4787 | tpacpi_leds[i].led = i; | 4979 | if (!tpacpi_is_led_restricted(i)) { |
4788 | 4980 | rc = tpacpi_init_led(i); | |
4789 | tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; | 4981 | if (rc < 0) { |
4790 | tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; | 4982 | led_exit(); |
4791 | if (led_supported == TPACPI_LED_570) | 4983 | return rc; |
4792 | tpacpi_leds[i].led_classdev.brightness_get = | 4984 | } |
4793 | &led_sysfs_get; | ||
4794 | |||
4795 | tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i]; | ||
4796 | |||
4797 | INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker); | ||
4798 | |||
4799 | rc = led_classdev_register(&tpacpi_pdev->dev, | ||
4800 | &tpacpi_leds[i].led_classdev); | ||
4801 | if (rc < 0) { | ||
4802 | tpacpi_leds[i].led_classdev.name = NULL; | ||
4803 | led_exit(); | ||
4804 | return rc; | ||
4805 | } | 4985 | } |
4806 | } | 4986 | } |
4807 | 4987 | ||
4988 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | ||
4989 | if (led_supported != TPACPI_LED_NONE) | ||
4990 | printk(TPACPI_NOTICE | ||
4991 | "warning: userspace override of important " | ||
4992 | "firmware LEDs is enabled\n"); | ||
4993 | #endif | ||
4808 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; | 4994 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; |
4809 | } | 4995 | } |
4810 | 4996 | ||
@@ -5340,6 +5526,20 @@ static struct ibm_struct ecdump_driver_data = { | |||
5340 | 5526 | ||
5341 | #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" | 5527 | #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" |
5342 | 5528 | ||
5529 | /* | ||
5530 | * ThinkPads can read brightness from two places: EC HBRV (0x31), or | ||
5531 | * CMOS NVRAM byte 0x5E, bits 0-3. | ||
5532 | * | ||
5533 | * EC HBRV (0x31) has the following layout | ||
5534 | * Bit 7: unknown function | ||
5535 | * Bit 6: unknown function | ||
5536 | * Bit 5: Z: honour scale changes, NZ: ignore scale changes | ||
5537 | * Bit 4: must be set to zero to avoid problems | ||
5538 | * Bit 3-0: backlight brightness level | ||
5539 | * | ||
5540 | * brightness_get_raw returns status data in the HBRV layout | ||
5541 | */ | ||
5542 | |||
5343 | enum { | 5543 | enum { |
5344 | TP_EC_BACKLIGHT = 0x31, | 5544 | TP_EC_BACKLIGHT = 0x31, |
5345 | 5545 | ||
@@ -5349,108 +5549,164 @@ enum { | |||
5349 | TP_EC_BACKLIGHT_MAPSW = 0x20, | 5549 | TP_EC_BACKLIGHT_MAPSW = 0x20, |
5350 | }; | 5550 | }; |
5351 | 5551 | ||
5552 | enum tpacpi_brightness_access_mode { | ||
5553 | TPACPI_BRGHT_MODE_AUTO = 0, /* Not implemented yet */ | ||
5554 | TPACPI_BRGHT_MODE_EC, /* EC control */ | ||
5555 | TPACPI_BRGHT_MODE_UCMS_STEP, /* UCMS step-based control */ | ||
5556 | TPACPI_BRGHT_MODE_ECNVRAM, /* EC control w/ NVRAM store */ | ||
5557 | TPACPI_BRGHT_MODE_MAX | ||
5558 | }; | ||
5559 | |||
5352 | static struct backlight_device *ibm_backlight_device; | 5560 | static struct backlight_device *ibm_backlight_device; |
5353 | static int brightness_mode; | 5561 | |
5562 | static enum tpacpi_brightness_access_mode brightness_mode = | ||
5563 | TPACPI_BRGHT_MODE_MAX; | ||
5564 | |||
5354 | static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ | 5565 | static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ |
5355 | 5566 | ||
5356 | static struct mutex brightness_mutex; | 5567 | static struct mutex brightness_mutex; |
5357 | 5568 | ||
5358 | /* | 5569 | /* NVRAM brightness access, |
5359 | * ThinkPads can read brightness from two places: EC 0x31, or | 5570 | * call with brightness_mutex held! */ |
5360 | * CMOS NVRAM byte 0x5E, bits 0-3. | 5571 | static unsigned int tpacpi_brightness_nvram_get(void) |
5361 | * | ||
5362 | * EC 0x31 has the following layout | ||
5363 | * Bit 7: unknown function | ||
5364 | * Bit 6: unknown function | ||
5365 | * Bit 5: Z: honour scale changes, NZ: ignore scale changes | ||
5366 | * Bit 4: must be set to zero to avoid problems | ||
5367 | * Bit 3-0: backlight brightness level | ||
5368 | * | ||
5369 | * brightness_get_raw returns status data in the EC 0x31 layout | ||
5370 | */ | ||
5371 | static int brightness_get_raw(int *status) | ||
5372 | { | 5572 | { |
5373 | u8 lec = 0, lcmos = 0, level = 0; | 5573 | u8 lnvram; |
5374 | 5574 | ||
5375 | if (brightness_mode & 1) { | 5575 | lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) |
5376 | if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) | 5576 | & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) |
5377 | return -EIO; | 5577 | >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; |
5378 | level = lec & TP_EC_BACKLIGHT_LVLMSK; | 5578 | lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07; |
5379 | }; | 5579 | |
5380 | if (brightness_mode & 2) { | 5580 | return lnvram; |
5381 | lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) | 5581 | } |
5382 | & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) | 5582 | |
5383 | >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; | 5583 | static void tpacpi_brightness_checkpoint_nvram(void) |
5384 | lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; | 5584 | { |
5385 | level = lcmos; | 5585 | u8 lec = 0; |
5386 | } | 5586 | u8 b_nvram; |
5387 | 5587 | ||
5388 | if (brightness_mode == 3) { | 5588 | if (brightness_mode != TPACPI_BRGHT_MODE_ECNVRAM) |
5389 | *status = lec; /* Prefer EC, CMOS is just a backing store */ | 5589 | return; |
5390 | lec &= TP_EC_BACKLIGHT_LVLMSK; | 5590 | |
5391 | if (lec == lcmos) | 5591 | vdbg_printk(TPACPI_DBG_BRGHT, |
5392 | tp_warned.bright_cmos_ec_unsync = 0; | 5592 | "trying to checkpoint backlight level to NVRAM...\n"); |
5393 | else { | 5593 | |
5394 | if (!tp_warned.bright_cmos_ec_unsync) { | 5594 | if (mutex_lock_killable(&brightness_mutex) < 0) |
5395 | printk(TPACPI_ERR | 5595 | return; |
5396 | "CMOS NVRAM (%u) and EC (%u) do not " | 5596 | |
5397 | "agree on display brightness level\n", | 5597 | if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) |
5398 | (unsigned int) lcmos, | 5598 | goto unlock; |
5399 | (unsigned int) lec); | 5599 | lec &= TP_EC_BACKLIGHT_LVLMSK; |
5400 | tp_warned.bright_cmos_ec_unsync = 1; | 5600 | b_nvram = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS); |
5401 | } | 5601 | |
5602 | if (lec != ((b_nvram & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) | ||
5603 | >> TP_NVRAM_POS_LEVEL_BRIGHTNESS)) { | ||
5604 | /* NVRAM needs update */ | ||
5605 | b_nvram &= ~(TP_NVRAM_MASK_LEVEL_BRIGHTNESS << | ||
5606 | TP_NVRAM_POS_LEVEL_BRIGHTNESS); | ||
5607 | b_nvram |= lec; | ||
5608 | nvram_write_byte(b_nvram, TP_NVRAM_ADDR_BRIGHTNESS); | ||
5609 | dbg_printk(TPACPI_DBG_BRGHT, | ||
5610 | "updated NVRAM backlight level to %u (0x%02x)\n", | ||
5611 | (unsigned int) lec, (unsigned int) b_nvram); | ||
5612 | } else | ||
5613 | vdbg_printk(TPACPI_DBG_BRGHT, | ||
5614 | "NVRAM backlight level already is %u (0x%02x)\n", | ||
5615 | (unsigned int) lec, (unsigned int) b_nvram); | ||
5616 | |||
5617 | unlock: | ||
5618 | mutex_unlock(&brightness_mutex); | ||
5619 | } | ||
5620 | |||
5621 | |||
5622 | /* call with brightness_mutex held! */ | ||
5623 | static int tpacpi_brightness_get_raw(int *status) | ||
5624 | { | ||
5625 | u8 lec = 0; | ||
5626 | |||
5627 | switch (brightness_mode) { | ||
5628 | case TPACPI_BRGHT_MODE_UCMS_STEP: | ||
5629 | *status = tpacpi_brightness_nvram_get(); | ||
5630 | return 0; | ||
5631 | case TPACPI_BRGHT_MODE_EC: | ||
5632 | case TPACPI_BRGHT_MODE_ECNVRAM: | ||
5633 | if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) | ||
5402 | return -EIO; | 5634 | return -EIO; |
5403 | } | 5635 | *status = lec; |
5404 | } else { | 5636 | return 0; |
5405 | *status = level; | 5637 | default: |
5638 | return -ENXIO; | ||
5406 | } | 5639 | } |
5640 | } | ||
5641 | |||
5642 | /* call with brightness_mutex held! */ | ||
5643 | /* do NOT call with illegal backlight level value */ | ||
5644 | static int tpacpi_brightness_set_ec(unsigned int value) | ||
5645 | { | ||
5646 | u8 lec = 0; | ||
5647 | |||
5648 | if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) | ||
5649 | return -EIO; | ||
5650 | |||
5651 | if (unlikely(!acpi_ec_write(TP_EC_BACKLIGHT, | ||
5652 | (lec & TP_EC_BACKLIGHT_CMDMSK) | | ||
5653 | (value & TP_EC_BACKLIGHT_LVLMSK)))) | ||
5654 | return -EIO; | ||
5655 | |||
5656 | return 0; | ||
5657 | } | ||
5658 | |||
5659 | /* call with brightness_mutex held! */ | ||
5660 | static int tpacpi_brightness_set_ucmsstep(unsigned int value) | ||
5661 | { | ||
5662 | int cmos_cmd, inc; | ||
5663 | unsigned int current_value, i; | ||
5664 | |||
5665 | current_value = tpacpi_brightness_nvram_get(); | ||
5666 | |||
5667 | if (value == current_value) | ||
5668 | return 0; | ||
5669 | |||
5670 | cmos_cmd = (value > current_value) ? | ||
5671 | TP_CMOS_BRIGHTNESS_UP : | ||
5672 | TP_CMOS_BRIGHTNESS_DOWN; | ||
5673 | inc = (value > current_value) ? 1 : -1; | ||
5674 | |||
5675 | for (i = current_value; i != value; i += inc) | ||
5676 | if (issue_thinkpad_cmos_command(cmos_cmd)) | ||
5677 | return -EIO; | ||
5407 | 5678 | ||
5408 | return 0; | 5679 | return 0; |
5409 | } | 5680 | } |
5410 | 5681 | ||
5411 | /* May return EINTR which can always be mapped to ERESTARTSYS */ | 5682 | /* May return EINTR which can always be mapped to ERESTARTSYS */ |
5412 | static int brightness_set(int value) | 5683 | static int brightness_set(unsigned int value) |
5413 | { | 5684 | { |
5414 | int cmos_cmd, inc, i, res; | 5685 | int res; |
5415 | int current_value; | ||
5416 | int command_bits; | ||
5417 | 5686 | ||
5418 | if (value > ((tp_features.bright_16levels)? 15 : 7) || | 5687 | if (value > ((tp_features.bright_16levels)? 15 : 7) || |
5419 | value < 0) | 5688 | value < 0) |
5420 | return -EINVAL; | 5689 | return -EINVAL; |
5421 | 5690 | ||
5691 | vdbg_printk(TPACPI_DBG_BRGHT, | ||
5692 | "set backlight level to %d\n", value); | ||
5693 | |||
5422 | res = mutex_lock_killable(&brightness_mutex); | 5694 | res = mutex_lock_killable(&brightness_mutex); |
5423 | if (res < 0) | 5695 | if (res < 0) |
5424 | return res; | 5696 | return res; |
5425 | 5697 | ||
5426 | res = brightness_get_raw(¤t_value); | 5698 | switch (brightness_mode) { |
5427 | if (res < 0) | 5699 | case TPACPI_BRGHT_MODE_EC: |
5428 | goto errout; | 5700 | case TPACPI_BRGHT_MODE_ECNVRAM: |
5429 | 5701 | res = tpacpi_brightness_set_ec(value); | |
5430 | command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; | 5702 | break; |
5431 | current_value &= TP_EC_BACKLIGHT_LVLMSK; | 5703 | case TPACPI_BRGHT_MODE_UCMS_STEP: |
5432 | 5704 | res = tpacpi_brightness_set_ucmsstep(value); | |
5433 | cmos_cmd = value > current_value ? | 5705 | break; |
5434 | TP_CMOS_BRIGHTNESS_UP : | 5706 | default: |
5435 | TP_CMOS_BRIGHTNESS_DOWN; | 5707 | res = -ENXIO; |
5436 | inc = (value > current_value)? 1 : -1; | ||
5437 | |||
5438 | res = 0; | ||
5439 | for (i = current_value; i != value; i += inc) { | ||
5440 | if ((brightness_mode & 2) && | ||
5441 | issue_thinkpad_cmos_command(cmos_cmd)) { | ||
5442 | res = -EIO; | ||
5443 | goto errout; | ||
5444 | } | ||
5445 | if ((brightness_mode & 1) && | ||
5446 | !acpi_ec_write(TP_EC_BACKLIGHT, | ||
5447 | (i + inc) | command_bits)) { | ||
5448 | res = -EIO; | ||
5449 | goto errout;; | ||
5450 | } | ||
5451 | } | 5708 | } |
5452 | 5709 | ||
5453 | errout: | ||
5454 | mutex_unlock(&brightness_mutex); | 5710 | mutex_unlock(&brightness_mutex); |
5455 | return res; | 5711 | return res; |
5456 | } | 5712 | } |
@@ -5459,21 +5715,34 @@ errout: | |||
5459 | 5715 | ||
5460 | static int brightness_update_status(struct backlight_device *bd) | 5716 | static int brightness_update_status(struct backlight_device *bd) |
5461 | { | 5717 | { |
5462 | /* it is the backlight class's job (caller) to handle | 5718 | unsigned int level = |
5463 | * EINTR and other errors properly */ | ||
5464 | return brightness_set( | ||
5465 | (bd->props.fb_blank == FB_BLANK_UNBLANK && | 5719 | (bd->props.fb_blank == FB_BLANK_UNBLANK && |
5466 | bd->props.power == FB_BLANK_UNBLANK) ? | 5720 | bd->props.power == FB_BLANK_UNBLANK) ? |
5467 | bd->props.brightness : 0); | 5721 | bd->props.brightness : 0; |
5722 | |||
5723 | dbg_printk(TPACPI_DBG_BRGHT, | ||
5724 | "backlight: attempt to set level to %d\n", | ||
5725 | level); | ||
5726 | |||
5727 | /* it is the backlight class's job (caller) to handle | ||
5728 | * EINTR and other errors properly */ | ||
5729 | return brightness_set(level); | ||
5468 | } | 5730 | } |
5469 | 5731 | ||
5470 | static int brightness_get(struct backlight_device *bd) | 5732 | static int brightness_get(struct backlight_device *bd) |
5471 | { | 5733 | { |
5472 | int status, res; | 5734 | int status, res; |
5473 | 5735 | ||
5474 | res = brightness_get_raw(&status); | 5736 | res = mutex_lock_killable(&brightness_mutex); |
5475 | if (res < 0) | 5737 | if (res < 0) |
5476 | return 0; /* FIXME: teach backlight about error handling */ | 5738 | return 0; |
5739 | |||
5740 | res = tpacpi_brightness_get_raw(&status); | ||
5741 | |||
5742 | mutex_unlock(&brightness_mutex); | ||
5743 | |||
5744 | if (res < 0) | ||
5745 | return 0; | ||
5477 | 5746 | ||
5478 | return status & TP_EC_BACKLIGHT_LVLMSK; | 5747 | return status & TP_EC_BACKLIGHT_LVLMSK; |
5479 | } | 5748 | } |
@@ -5523,7 +5792,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
5523 | } | 5792 | } |
5524 | 5793 | ||
5525 | if (!brightness_enable) { | 5794 | if (!brightness_enable) { |
5526 | dbg_printk(TPACPI_DBG_INIT, | 5795 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, |
5527 | "brightness support disabled by " | 5796 | "brightness support disabled by " |
5528 | "module parameter\n"); | 5797 | "module parameter\n"); |
5529 | return 1; | 5798 | return 1; |
@@ -5538,20 +5807,38 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
5538 | if (b == 16) | 5807 | if (b == 16) |
5539 | tp_features.bright_16levels = 1; | 5808 | tp_features.bright_16levels = 1; |
5540 | 5809 | ||
5541 | if (!brightness_mode) { | 5810 | /* |
5542 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) | 5811 | * Check for module parameter bogosity, note that we |
5543 | brightness_mode = 2; | 5812 | * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be |
5544 | else | 5813 | * able to detect "unspecified" |
5545 | brightness_mode = 3; | 5814 | */ |
5815 | if (brightness_mode > TPACPI_BRGHT_MODE_MAX) | ||
5816 | return -EINVAL; | ||
5546 | 5817 | ||
5547 | dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", | 5818 | /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ |
5548 | brightness_mode); | 5819 | if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || |
5549 | } | 5820 | brightness_mode == TPACPI_BRGHT_MODE_MAX) { |
5821 | if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { | ||
5822 | /* | ||
5823 | * IBM models that define HBRV probably have | ||
5824 | * EC-based backlight level control | ||
5825 | */ | ||
5826 | if (acpi_evalf(ec_handle, NULL, "HBRV", "qd")) | ||
5827 | /* T40-T43, R50-R52, R50e, R51e, X31-X41 */ | ||
5828 | brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; | ||
5829 | else | ||
5830 | /* all other IBM ThinkPads */ | ||
5831 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | ||
5832 | } else | ||
5833 | /* All Lenovo ThinkPads */ | ||
5834 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | ||
5550 | 5835 | ||
5551 | if (brightness_mode > 3) | 5836 | dbg_printk(TPACPI_DBG_BRGHT, |
5552 | return -EINVAL; | 5837 | "selected brightness_mode=%d\n", |
5838 | brightness_mode); | ||
5839 | } | ||
5553 | 5840 | ||
5554 | if (brightness_get_raw(&b) < 0) | 5841 | if (tpacpi_brightness_get_raw(&b) < 0) |
5555 | return 1; | 5842 | return 1; |
5556 | 5843 | ||
5557 | if (tp_features.bright_16levels) | 5844 | if (tp_features.bright_16levels) |
@@ -5565,7 +5852,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
5565 | printk(TPACPI_ERR "Could not register backlight device\n"); | 5852 | printk(TPACPI_ERR "Could not register backlight device\n"); |
5566 | return PTR_ERR(ibm_backlight_device); | 5853 | return PTR_ERR(ibm_backlight_device); |
5567 | } | 5854 | } |
5568 | vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); | 5855 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, |
5856 | "brightness is supported\n"); | ||
5569 | 5857 | ||
5570 | ibm_backlight_device->props.max_brightness = | 5858 | ibm_backlight_device->props.max_brightness = |
5571 | (tp_features.bright_16levels)? 15 : 7; | 5859 | (tp_features.bright_16levels)? 15 : 7; |
@@ -5575,13 +5863,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
5575 | return 0; | 5863 | return 0; |
5576 | } | 5864 | } |
5577 | 5865 | ||
5866 | static void brightness_suspend(pm_message_t state) | ||
5867 | { | ||
5868 | tpacpi_brightness_checkpoint_nvram(); | ||
5869 | } | ||
5870 | |||
5871 | static void brightness_shutdown(void) | ||
5872 | { | ||
5873 | tpacpi_brightness_checkpoint_nvram(); | ||
5874 | } | ||
5875 | |||
5578 | static void brightness_exit(void) | 5876 | static void brightness_exit(void) |
5579 | { | 5877 | { |
5580 | if (ibm_backlight_device) { | 5878 | if (ibm_backlight_device) { |
5581 | vdbg_printk(TPACPI_DBG_EXIT, | 5879 | vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_BRGHT, |
5582 | "calling backlight_device_unregister()\n"); | 5880 | "calling backlight_device_unregister()\n"); |
5583 | backlight_device_unregister(ibm_backlight_device); | 5881 | backlight_device_unregister(ibm_backlight_device); |
5584 | } | 5882 | } |
5883 | |||
5884 | tpacpi_brightness_checkpoint_nvram(); | ||
5585 | } | 5885 | } |
5586 | 5886 | ||
5587 | static int brightness_read(char *p) | 5887 | static int brightness_read(char *p) |
@@ -5628,6 +5928,9 @@ static int brightness_write(char *buf) | |||
5628 | return -EINVAL; | 5928 | return -EINVAL; |
5629 | } | 5929 | } |
5630 | 5930 | ||
5931 | tpacpi_disclose_usertask("procfs brightness", | ||
5932 | "set level to %d\n", level); | ||
5933 | |||
5631 | /* | 5934 | /* |
5632 | * Now we know what the final level should be, so we try to set it. | 5935 | * Now we know what the final level should be, so we try to set it. |
5633 | * Doing it this way makes the syscall restartable in case of EINTR | 5936 | * Doing it this way makes the syscall restartable in case of EINTR |
@@ -5641,6 +5944,8 @@ static struct ibm_struct brightness_driver_data = { | |||
5641 | .read = brightness_read, | 5944 | .read = brightness_read, |
5642 | .write = brightness_write, | 5945 | .write = brightness_write, |
5643 | .exit = brightness_exit, | 5946 | .exit = brightness_exit, |
5947 | .suspend = brightness_suspend, | ||
5948 | .shutdown = brightness_shutdown, | ||
5644 | }; | 5949 | }; |
5645 | 5950 | ||
5646 | /************************************************************************* | 5951 | /************************************************************************* |
@@ -6086,6 +6391,9 @@ static int fan_set_level(int level) | |||
6086 | default: | 6391 | default: |
6087 | return -ENXIO; | 6392 | return -ENXIO; |
6088 | } | 6393 | } |
6394 | |||
6395 | vdbg_printk(TPACPI_DBG_FAN, | ||
6396 | "fan control: set fan control register to 0x%02x\n", level); | ||
6089 | return 0; | 6397 | return 0; |
6090 | } | 6398 | } |
6091 | 6399 | ||
@@ -6163,6 +6471,11 @@ static int fan_set_enable(void) | |||
6163 | } | 6471 | } |
6164 | 6472 | ||
6165 | mutex_unlock(&fan_mutex); | 6473 | mutex_unlock(&fan_mutex); |
6474 | |||
6475 | if (!rc) | ||
6476 | vdbg_printk(TPACPI_DBG_FAN, | ||
6477 | "fan control: set fan control register to 0x%02x\n", | ||
6478 | s); | ||
6166 | return rc; | 6479 | return rc; |
6167 | } | 6480 | } |
6168 | 6481 | ||
@@ -6199,6 +6512,9 @@ static int fan_set_disable(void) | |||
6199 | rc = -ENXIO; | 6512 | rc = -ENXIO; |
6200 | } | 6513 | } |
6201 | 6514 | ||
6515 | if (!rc) | ||
6516 | vdbg_printk(TPACPI_DBG_FAN, | ||
6517 | "fan control: set fan control register to 0\n"); | ||
6202 | 6518 | ||
6203 | mutex_unlock(&fan_mutex); | 6519 | mutex_unlock(&fan_mutex); |
6204 | return rc; | 6520 | return rc; |
@@ -6327,6 +6643,9 @@ static ssize_t fan_pwm1_enable_store(struct device *dev, | |||
6327 | if (parse_strtoul(buf, 2, &t)) | 6643 | if (parse_strtoul(buf, 2, &t)) |
6328 | return -EINVAL; | 6644 | return -EINVAL; |
6329 | 6645 | ||
6646 | tpacpi_disclose_usertask("hwmon pwm1_enable", | ||
6647 | "set fan mode to %lu\n", t); | ||
6648 | |||
6330 | switch (t) { | 6649 | switch (t) { |
6331 | case 0: | 6650 | case 0: |
6332 | level = TP_EC_FAN_FULLSPEED; | 6651 | level = TP_EC_FAN_FULLSPEED; |
@@ -6392,6 +6711,9 @@ static ssize_t fan_pwm1_store(struct device *dev, | |||
6392 | if (parse_strtoul(buf, 255, &s)) | 6711 | if (parse_strtoul(buf, 255, &s)) |
6393 | return -EINVAL; | 6712 | return -EINVAL; |
6394 | 6713 | ||
6714 | tpacpi_disclose_usertask("hwmon pwm1", | ||
6715 | "set fan speed to %lu\n", s); | ||
6716 | |||
6395 | /* scale down from 0-255 to 0-7 */ | 6717 | /* scale down from 0-255 to 0-7 */ |
6396 | newlevel = (s >> 5) & 0x07; | 6718 | newlevel = (s >> 5) & 0x07; |
6397 | 6719 | ||
@@ -6458,6 +6780,8 @@ static ssize_t fan_fan_watchdog_store(struct device_driver *drv, | |||
6458 | fan_watchdog_maxinterval = t; | 6780 | fan_watchdog_maxinterval = t; |
6459 | fan_watchdog_reset(); | 6781 | fan_watchdog_reset(); |
6460 | 6782 | ||
6783 | tpacpi_disclose_usertask("fan_watchdog", "set to %lu\n", t); | ||
6784 | |||
6461 | return count; | 6785 | return count; |
6462 | } | 6786 | } |
6463 | 6787 | ||
@@ -6479,7 +6803,8 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6479 | { | 6803 | { |
6480 | int rc; | 6804 | int rc; |
6481 | 6805 | ||
6482 | vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); | 6806 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, |
6807 | "initializing fan subdriver\n"); | ||
6483 | 6808 | ||
6484 | mutex_init(&fan_mutex); | 6809 | mutex_init(&fan_mutex); |
6485 | fan_status_access_mode = TPACPI_FAN_NONE; | 6810 | fan_status_access_mode = TPACPI_FAN_NONE; |
@@ -6538,7 +6863,8 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6538 | } | 6863 | } |
6539 | } | 6864 | } |
6540 | 6865 | ||
6541 | vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n", | 6866 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, |
6867 | "fan is %s, modes %d, %d\n", | ||
6542 | str_supported(fan_status_access_mode != TPACPI_FAN_NONE || | 6868 | str_supported(fan_status_access_mode != TPACPI_FAN_NONE || |
6543 | fan_control_access_mode != TPACPI_FAN_WR_NONE), | 6869 | fan_control_access_mode != TPACPI_FAN_WR_NONE), |
6544 | fan_status_access_mode, fan_control_access_mode); | 6870 | fan_status_access_mode, fan_control_access_mode); |
@@ -6547,7 +6873,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6547 | if (!fan_control_allowed) { | 6873 | if (!fan_control_allowed) { |
6548 | fan_control_access_mode = TPACPI_FAN_WR_NONE; | 6874 | fan_control_access_mode = TPACPI_FAN_WR_NONE; |
6549 | fan_control_commands = 0; | 6875 | fan_control_commands = 0; |
6550 | dbg_printk(TPACPI_DBG_INIT, | 6876 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, |
6551 | "fan control features disabled by parameter\n"); | 6877 | "fan control features disabled by parameter\n"); |
6552 | } | 6878 | } |
6553 | 6879 | ||
@@ -6576,7 +6902,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6576 | 6902 | ||
6577 | static void fan_exit(void) | 6903 | static void fan_exit(void) |
6578 | { | 6904 | { |
6579 | vdbg_printk(TPACPI_DBG_EXIT, | 6905 | vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_FAN, |
6580 | "cancelling any pending fan watchdog tasks\n"); | 6906 | "cancelling any pending fan watchdog tasks\n"); |
6581 | 6907 | ||
6582 | /* FIXME: can we really do this unconditionally? */ | 6908 | /* FIXME: can we really do this unconditionally? */ |
@@ -6757,6 +7083,9 @@ static int fan_write_cmd_level(const char *cmd, int *rc) | |||
6757 | if (*rc == -ENXIO) | 7083 | if (*rc == -ENXIO) |
6758 | printk(TPACPI_ERR "level command accepted for unsupported " | 7084 | printk(TPACPI_ERR "level command accepted for unsupported " |
6759 | "access mode %d", fan_control_access_mode); | 7085 | "access mode %d", fan_control_access_mode); |
7086 | else if (!*rc) | ||
7087 | tpacpi_disclose_usertask("procfs fan", | ||
7088 | "set level to %d\n", level); | ||
6760 | 7089 | ||
6761 | return 1; | 7090 | return 1; |
6762 | } | 7091 | } |
@@ -6770,6 +7099,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc) | |||
6770 | if (*rc == -ENXIO) | 7099 | if (*rc == -ENXIO) |
6771 | printk(TPACPI_ERR "enable command accepted for unsupported " | 7100 | printk(TPACPI_ERR "enable command accepted for unsupported " |
6772 | "access mode %d", fan_control_access_mode); | 7101 | "access mode %d", fan_control_access_mode); |
7102 | else if (!*rc) | ||
7103 | tpacpi_disclose_usertask("procfs fan", "enable\n"); | ||
6773 | 7104 | ||
6774 | return 1; | 7105 | return 1; |
6775 | } | 7106 | } |
@@ -6783,6 +7114,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc) | |||
6783 | if (*rc == -ENXIO) | 7114 | if (*rc == -ENXIO) |
6784 | printk(TPACPI_ERR "disable command accepted for unsupported " | 7115 | printk(TPACPI_ERR "disable command accepted for unsupported " |
6785 | "access mode %d", fan_control_access_mode); | 7116 | "access mode %d", fan_control_access_mode); |
7117 | else if (!*rc) | ||
7118 | tpacpi_disclose_usertask("procfs fan", "disable\n"); | ||
6786 | 7119 | ||
6787 | return 1; | 7120 | return 1; |
6788 | } | 7121 | } |
@@ -6801,6 +7134,9 @@ static int fan_write_cmd_speed(const char *cmd, int *rc) | |||
6801 | if (*rc == -ENXIO) | 7134 | if (*rc == -ENXIO) |
6802 | printk(TPACPI_ERR "speed command accepted for unsupported " | 7135 | printk(TPACPI_ERR "speed command accepted for unsupported " |
6803 | "access mode %d", fan_control_access_mode); | 7136 | "access mode %d", fan_control_access_mode); |
7137 | else if (!*rc) | ||
7138 | tpacpi_disclose_usertask("procfs fan", | ||
7139 | "set speed to %d\n", speed); | ||
6804 | 7140 | ||
6805 | return 1; | 7141 | return 1; |
6806 | } | 7142 | } |
@@ -6814,8 +7150,12 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc) | |||
6814 | 7150 | ||
6815 | if (interval < 0 || interval > 120) | 7151 | if (interval < 0 || interval > 120) |
6816 | *rc = -EINVAL; | 7152 | *rc = -EINVAL; |
6817 | else | 7153 | else { |
6818 | fan_watchdog_maxinterval = interval; | 7154 | fan_watchdog_maxinterval = interval; |
7155 | tpacpi_disclose_usertask("procfs fan", | ||
7156 | "set watchdog timer to %d\n", | ||
7157 | interval); | ||
7158 | } | ||
6819 | 7159 | ||
6820 | return 1; | 7160 | return 1; |
6821 | } | 7161 | } |
@@ -7244,10 +7584,10 @@ module_param_named(fan_control, fan_control_allowed, bool, 0); | |||
7244 | MODULE_PARM_DESC(fan_control, | 7584 | MODULE_PARM_DESC(fan_control, |
7245 | "Enables setting fan parameters features when true"); | 7585 | "Enables setting fan parameters features when true"); |
7246 | 7586 | ||
7247 | module_param_named(brightness_mode, brightness_mode, int, 0); | 7587 | module_param_named(brightness_mode, brightness_mode, uint, 0); |
7248 | MODULE_PARM_DESC(brightness_mode, | 7588 | MODULE_PARM_DESC(brightness_mode, |
7249 | "Selects brightness control strategy: " | 7589 | "Selects brightness control strategy: " |
7250 | "0=auto, 1=EC, 2=CMOS, 3=both"); | 7590 | "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); |
7251 | 7591 | ||
7252 | module_param(brightness_enable, uint, 0); | 7592 | module_param(brightness_enable, uint, 0); |
7253 | MODULE_PARM_DESC(brightness_enable, | 7593 | MODULE_PARM_DESC(brightness_enable, |
@@ -7517,9 +7857,6 @@ static int __init thinkpad_acpi_module_init(void) | |||
7517 | return 0; | 7857 | return 0; |
7518 | } | 7858 | } |
7519 | 7859 | ||
7520 | /* Please remove this in year 2009 */ | ||
7521 | MODULE_ALIAS("ibm_acpi"); | ||
7522 | |||
7523 | MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); | 7860 | MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); |
7524 | 7861 | ||
7525 | /* | 7862 | /* |