aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2009-09-12 14:22:14 -0400
committerLen Brown <len.brown@intel.com>2009-09-19 00:53:04 -0400
commitdb25f16d1dcce8de12f2f5daf884cda02196b28c (patch)
tree12abde8e97c57de182d9a0b8f6689664546d09f6 /drivers/platform
parente675abafcc0df38125e6e94a9ba91c92fe774f52 (diff)
thinkpad-acpi: hotkey poll fixes
Fix some locking, avoid exiting the kthread before kthread_stop() is called on it, and clean up the hotkey poll routines a little bit. Also, restore bits in the firmware mask after hotkey_source_mask is changed. Without this, we leave events disabled... Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c108
1 files changed, 73 insertions, 35 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index d69ab3f0bdbc..679a73b43191 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1922,16 +1922,42 @@ struct tp_nvram_state {
1922 u8 volume_level; 1922 u8 volume_level;
1923}; 1923};
1924 1924
1925/* kthread for the hotkey poller */
1925static struct task_struct *tpacpi_hotkey_task; 1926static struct task_struct *tpacpi_hotkey_task;
1926static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ 1927
1927static int hotkey_poll_freq = 10; /* Hz */ 1928/* Acquired while the poller kthread is running, use to sync start/stop */
1928static struct mutex hotkey_thread_mutex; 1929static struct mutex hotkey_thread_mutex;
1930
1931/*
1932 * Acquire mutex to write poller control variables.
1933 * Increment hotkey_config_change when changing them.
1934 *
1935 * See HOTKEY_CONFIG_CRITICAL_START/HOTKEY_CONFIG_CRITICAL_END
1936 */
1929static struct mutex hotkey_thread_data_mutex; 1937static struct mutex hotkey_thread_data_mutex;
1930static unsigned int hotkey_config_change; 1938static unsigned int hotkey_config_change;
1931 1939
1940/*
1941 * hotkey poller control variables
1942 *
1943 * Must be atomic or readers will also need to acquire mutex
1944 */
1945static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */
1946static unsigned int hotkey_poll_freq = 10; /* Hz */
1947
1948#define HOTKEY_CONFIG_CRITICAL_START \
1949 do { \
1950 mutex_lock(&hotkey_thread_data_mutex); \
1951 hotkey_config_change++; \
1952 } while (0);
1953#define HOTKEY_CONFIG_CRITICAL_END \
1954 mutex_unlock(&hotkey_thread_data_mutex);
1955
1932#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 1956#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1933 1957
1934#define hotkey_source_mask 0U 1958#define hotkey_source_mask 0U
1959#define HOTKEY_CONFIG_CRITICAL_START
1960#define HOTKEY_CONFIG_CRITICAL_END
1935 1961
1936#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 1962#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1937 1963
@@ -1956,19 +1982,6 @@ static u16 *hotkey_keycode_map;
1956 1982
1957static struct attribute_set *hotkey_dev_attributes; 1983static struct attribute_set *hotkey_dev_attributes;
1958 1984
1959#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
1960#define HOTKEY_CONFIG_CRITICAL_START \
1961 do { \
1962 mutex_lock(&hotkey_thread_data_mutex); \
1963 hotkey_config_change++; \
1964 } while (0);
1965#define HOTKEY_CONFIG_CRITICAL_END \
1966 mutex_unlock(&hotkey_thread_data_mutex);
1967#else
1968#define HOTKEY_CONFIG_CRITICAL_START
1969#define HOTKEY_CONFIG_CRITICAL_END
1970#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1971
1972/* HKEY.MHKG() return bits */ 1985/* HKEY.MHKG() return bits */
1973#define TP_HOTKEY_TABLET_MASK (1 << 3) 1986#define TP_HOTKEY_TABLET_MASK (1 << 3)
1974 1987
@@ -2013,7 +2026,9 @@ static int hotkey_mask_get(void)
2013 if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) 2026 if (!acpi_evalf(hkey_handle, &m, "DHKN", "d"))
2014 return -EIO; 2027 return -EIO;
2015 } 2028 }
2029 HOTKEY_CONFIG_CRITICAL_START
2016 hotkey_mask = m | (hotkey_source_mask & hotkey_mask); 2030 hotkey_mask = m | (hotkey_source_mask & hotkey_mask);
2031 HOTKEY_CONFIG_CRITICAL_END
2017 2032
2018 return 0; 2033 return 0;
2019} 2034}
@@ -2266,6 +2281,7 @@ static int hotkey_kthread(void *data)
2266 unsigned int si, so; 2281 unsigned int si, so;
2267 unsigned long t; 2282 unsigned long t;
2268 unsigned int change_detector, must_reset; 2283 unsigned int change_detector, must_reset;
2284 unsigned int poll_freq;
2269 2285
2270 mutex_lock(&hotkey_thread_mutex); 2286 mutex_lock(&hotkey_thread_mutex);
2271 2287
@@ -2282,12 +2298,17 @@ static int hotkey_kthread(void *data)
2282 mutex_lock(&hotkey_thread_data_mutex); 2298 mutex_lock(&hotkey_thread_data_mutex);
2283 change_detector = hotkey_config_change; 2299 change_detector = hotkey_config_change;
2284 mask = hotkey_source_mask & hotkey_mask; 2300 mask = hotkey_source_mask & hotkey_mask;
2301 poll_freq = hotkey_poll_freq;
2285 mutex_unlock(&hotkey_thread_data_mutex); 2302 mutex_unlock(&hotkey_thread_data_mutex);
2286 hotkey_read_nvram(&s[so], mask); 2303 hotkey_read_nvram(&s[so], mask);
2287 2304
2288 while (!kthread_should_stop() && hotkey_poll_freq) { 2305 while (!kthread_should_stop()) {
2289 if (t == 0) 2306 if (t == 0) {
2290 t = 1000/hotkey_poll_freq; 2307 if (likely(poll_freq))
2308 t = 1000/poll_freq;
2309 else
2310 t = 100; /* should never happen... */
2311 }
2291 t = msleep_interruptible(t); 2312 t = msleep_interruptible(t);
2292 if (unlikely(kthread_should_stop())) 2313 if (unlikely(kthread_should_stop()))
2293 break; 2314 break;
@@ -2303,6 +2324,7 @@ static int hotkey_kthread(void *data)
2303 change_detector = hotkey_config_change; 2324 change_detector = hotkey_config_change;
2304 } 2325 }
2305 mask = hotkey_source_mask & hotkey_mask; 2326 mask = hotkey_source_mask & hotkey_mask;
2327 poll_freq = hotkey_poll_freq;
2306 mutex_unlock(&hotkey_thread_data_mutex); 2328 mutex_unlock(&hotkey_thread_data_mutex);
2307 2329
2308 if (likely(mask)) { 2330 if (likely(mask)) {
@@ -2322,6 +2344,7 @@ exit:
2322 return 0; 2344 return 0;
2323} 2345}
2324 2346
2347/* call with hotkey_mutex held */
2325static void hotkey_poll_stop_sync(void) 2348static void hotkey_poll_stop_sync(void)
2326{ 2349{
2327 if (tpacpi_hotkey_task) { 2350 if (tpacpi_hotkey_task) {
@@ -2338,10 +2361,11 @@ static void hotkey_poll_stop_sync(void)
2338} 2361}
2339 2362
2340/* call with hotkey_mutex held */ 2363/* call with hotkey_mutex held */
2341static void hotkey_poll_setup(int may_warn) 2364static void hotkey_poll_setup(bool may_warn)
2342{ 2365{
2343 if ((hotkey_source_mask & hotkey_mask) != 0 && 2366 u32 hotkeys_to_poll = hotkey_source_mask & hotkey_mask;
2344 hotkey_poll_freq > 0 && 2367
2368 if (hotkeys_to_poll != 0 && hotkey_poll_freq > 0 &&
2345 (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { 2369 (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
2346 if (!tpacpi_hotkey_task) { 2370 if (!tpacpi_hotkey_task) {
2347 tpacpi_hotkey_task = kthread_run(hotkey_kthread, 2371 tpacpi_hotkey_task = kthread_run(hotkey_kthread,
@@ -2355,26 +2379,37 @@ static void hotkey_poll_setup(int may_warn)
2355 } 2379 }
2356 } else { 2380 } else {
2357 hotkey_poll_stop_sync(); 2381 hotkey_poll_stop_sync();
2358 if (may_warn && 2382 if (may_warn && hotkeys_to_poll != 0 &&
2359 hotkey_source_mask != 0 && hotkey_poll_freq == 0) { 2383 hotkey_poll_freq == 0) {
2360 printk(TPACPI_NOTICE 2384 printk(TPACPI_NOTICE
2361 "hot keys 0x%08x require polling, " 2385 "hot keys 0x%08x require polling, "
2362 "which is currently disabled\n", 2386 "which is currently disabled\n",
2363 hotkey_source_mask); 2387 hotkeys_to_poll);
2364 } 2388 }
2365 } 2389 }
2366} 2390}
2367 2391
2368static void hotkey_poll_setup_safe(int may_warn) 2392static void hotkey_poll_setup_safe(bool may_warn)
2369{ 2393{
2370 mutex_lock(&hotkey_mutex); 2394 mutex_lock(&hotkey_mutex);
2371 hotkey_poll_setup(may_warn); 2395 hotkey_poll_setup(may_warn);
2372 mutex_unlock(&hotkey_mutex); 2396 mutex_unlock(&hotkey_mutex);
2373} 2397}
2374 2398
2399/* call with hotkey_mutex held */
2400static void hotkey_poll_set_freq(unsigned int freq)
2401{
2402 if (!freq)
2403 hotkey_poll_stop_sync();
2404
2405 HOTKEY_CONFIG_CRITICAL_START
2406 hotkey_poll_freq = freq;
2407 HOTKEY_CONFIG_CRITICAL_END
2408}
2409
2375#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 2410#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
2376 2411
2377static void hotkey_poll_setup_safe(int __unused) 2412static void hotkey_poll_setup_safe(bool __unused)
2378{ 2413{
2379} 2414}
2380 2415
@@ -2392,7 +2427,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2392 case TPACPI_LIFE_EXITING: 2427 case TPACPI_LIFE_EXITING:
2393 return -EBUSY; 2428 return -EBUSY;
2394 case TPACPI_LIFE_RUNNING: 2429 case TPACPI_LIFE_RUNNING:
2395 hotkey_poll_setup_safe(0); 2430 hotkey_poll_setup_safe(false);
2396 return 0; 2431 return 0;
2397 } 2432 }
2398 2433
@@ -2405,7 +2440,7 @@ static void hotkey_inputdev_close(struct input_dev *dev)
2405{ 2440{
2406 /* disable hotkey polling when possible */ 2441 /* disable hotkey polling when possible */
2407 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) 2442 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING)
2408 hotkey_poll_setup_safe(0); 2443 hotkey_poll_setup_safe(false);
2409} 2444}
2410 2445
2411/* sysfs hotkey enable ------------------------------------------------- */ 2446/* sysfs hotkey enable ------------------------------------------------- */
@@ -2479,7 +2514,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
2479 res = hotkey_mask_set(t); 2514 res = hotkey_mask_set(t);
2480 2515
2481#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL 2516#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2482 hotkey_poll_setup(1); 2517 hotkey_poll_setup(true);
2483#endif 2518#endif
2484 2519
2485 mutex_unlock(&hotkey_mutex); 2520 mutex_unlock(&hotkey_mutex);
@@ -2568,7 +2603,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
2568 hotkey_source_mask = t; 2603 hotkey_source_mask = t;
2569 HOTKEY_CONFIG_CRITICAL_END 2604 HOTKEY_CONFIG_CRITICAL_END
2570 2605
2571 hotkey_poll_setup(1); 2606 hotkey_poll_setup(true);
2607 hotkey_mask_set(hotkey_mask);
2572 2608
2573 mutex_unlock(&hotkey_mutex); 2609 mutex_unlock(&hotkey_mutex);
2574 2610
@@ -2601,9 +2637,9 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
2601 if (mutex_lock_killable(&hotkey_mutex)) 2637 if (mutex_lock_killable(&hotkey_mutex))
2602 return -ERESTARTSYS; 2638 return -ERESTARTSYS;
2603 2639
2604 hotkey_poll_freq = t; 2640 hotkey_poll_set_freq(t);
2641 hotkey_poll_setup(true);
2605 2642
2606 hotkey_poll_setup(1);
2607 mutex_unlock(&hotkey_mutex); 2643 mutex_unlock(&hotkey_mutex);
2608 2644
2609 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); 2645 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
@@ -2794,7 +2830,9 @@ static void tpacpi_send_radiosw_update(void)
2794static void hotkey_exit(void) 2830static void hotkey_exit(void)
2795{ 2831{
2796#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL 2832#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2833 mutex_lock(&hotkey_mutex);
2797 hotkey_poll_stop_sync(); 2834 hotkey_poll_stop_sync();
2835 mutex_unlock(&hotkey_mutex);
2798#endif 2836#endif
2799 2837
2800 if (hotkey_dev_attributes) 2838 if (hotkey_dev_attributes)
@@ -3031,7 +3069,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3031 } 3069 }
3032 3070
3033 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3071 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3034 "hotkey source mask 0x%08x, polling freq %d\n", 3072 "hotkey source mask 0x%08x, polling freq %u\n",
3035 hotkey_source_mask, hotkey_poll_freq); 3073 hotkey_source_mask, hotkey_poll_freq);
3036#endif 3074#endif
3037 3075
@@ -3169,7 +3207,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3169 tpacpi_inputdev->open = &hotkey_inputdev_open; 3207 tpacpi_inputdev->open = &hotkey_inputdev_open;
3170 tpacpi_inputdev->close = &hotkey_inputdev_close; 3208 tpacpi_inputdev->close = &hotkey_inputdev_close;
3171 3209
3172 hotkey_poll_setup_safe(1); 3210 hotkey_poll_setup_safe(true);
3173 tpacpi_send_radiosw_update(); 3211 tpacpi_send_radiosw_update();
3174 tpacpi_input_send_tabletsw(); 3212 tpacpi_input_send_tabletsw();
3175 3213
@@ -3457,7 +3495,7 @@ static void hotkey_resume(void)
3457 hotkey_tablet_mode_notify_change(); 3495 hotkey_tablet_mode_notify_change();
3458 hotkey_wakeup_reason_notify_change(); 3496 hotkey_wakeup_reason_notify_change();
3459 hotkey_wakeup_hotunplug_complete_notify_change(); 3497 hotkey_wakeup_hotunplug_complete_notify_change();
3460 hotkey_poll_setup_safe(0); 3498 hotkey_poll_setup_safe(false);
3461} 3499}
3462 3500
3463/* procfs -------------------------------------------------------------- */ 3501/* procfs -------------------------------------------------------------- */