aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/thinkpad_acpi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 12:32:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 12:32:11 -0400
commitc11f6c82581e8be4e1829c677db54e7f55cebece (patch)
tree1a116241b0831ded998aabe800bdc24104cbd826 /drivers/platform/x86/thinkpad_acpi.c
parent40aba218969914d1b225e742617adb921cf94eae (diff)
parent193a6dec1c0246a80b6d0101e4f351ccf877bcac (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (119 commits) ACPI: don't pass handle for fixed hardware notifications ACPI: remove null pointer checks in deferred execution path ACPI: simplify deferred execution path acerhdf: additional BIOS versions acerhdf: convert to dev_pm_ops acerhdf: fix fan control for AOA150 model thermal: add missing Kconfig dependency acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file hp-wmi: fix rfkill memory leak on unload ACPI: remove unnecessary #ifdef CONFIG_DMI ACPI: linux/acpi.h should not include linux/dmi.h hwmon driver for ACPI 4.0 power meters topstar-laptop: add new driver for hotkeys support on Topstar N01 thinkpad_acpi: fix rfkill memory leak on unload thinkpad-acpi: report brightness events when required thinkpad-acpi: don't poll by default any of the reserved hotkeys thinkpad-acpi: Fix procfs hotkey reset command thinkpad-acpi: deprecate hotkey_bios_mask thinkpad-acpi: hotkey poll fixes thinkpad-acpi: be more strict when detecting a ThinkPad ...
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c382
1 files changed, 310 insertions, 72 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index e8560085250..f78d2750392 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1278,6 +1278,7 @@ static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id)
1278 tp_rfk = tpacpi_rfkill_switches[id]; 1278 tp_rfk = tpacpi_rfkill_switches[id];
1279 if (tp_rfk) { 1279 if (tp_rfk) {
1280 rfkill_unregister(tp_rfk->rfkill); 1280 rfkill_unregister(tp_rfk->rfkill);
1281 rfkill_destroy(tp_rfk->rfkill);
1281 tpacpi_rfkill_switches[id] = NULL; 1282 tpacpi_rfkill_switches[id] = NULL;
1282 kfree(tp_rfk); 1283 kfree(tp_rfk);
1283 } 1284 }
@@ -1601,6 +1602,196 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
1601#endif 1602#endif
1602} 1603}
1603 1604
1605/*************************************************************************
1606 * Firmware Data
1607 */
1608
1609/*
1610 * Table of recommended minimum BIOS versions
1611 *
1612 * Reasons for listing:
1613 * 1. Stable BIOS, listed because the unknown ammount of
1614 * bugs and bad ACPI behaviour on older versions
1615 *
1616 * 2. BIOS or EC fw with known bugs that trigger on Linux
1617 *
1618 * 3. BIOS with known reduced functionality in older versions
1619 *
1620 * We recommend the latest BIOS and EC version.
1621 * We only support the latest BIOS and EC fw version as a rule.
1622 *
1623 * Sources: IBM ThinkPad Public Web Documents (update changelogs),
1624 * Information from users in ThinkWiki
1625 *
1626 * WARNING: we use this table also to detect that the machine is
1627 * a ThinkPad in some cases, so don't remove entries lightly.
1628 */
1629
1630#define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \
1631 { .vendor = (__v), \
1632 .bios = TPID(__id1, __id2), \
1633 .ec = TPACPI_MATCH_ANY, \
1634 .quirks = TPACPI_MATCH_ANY << 16 \
1635 | (__bv1) << 8 | (__bv2) }
1636
1637#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \
1638 __eid1, __eid2, __ev1, __ev2) \
1639 { .vendor = (__v), \
1640 .bios = TPID(__bid1, __bid2), \
1641 .ec = TPID(__eid1, __eid2), \
1642 .quirks = (__ev1) << 24 | (__ev2) << 16 \
1643 | (__bv1) << 8 | (__bv2) }
1644
1645#define TPV_QI0(__id1, __id2, __bv1, __bv2) \
1646 TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
1647
1648#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1649 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
1650 __bv1, __bv2, __id1, __id2, __ev1, __ev2)
1651
1652#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \
1653 __eid1, __eid2, __ev1, __ev2) \
1654 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
1655 __bv1, __bv2, __eid1, __eid2, __ev1, __ev2)
1656
1657#define TPV_QL0(__id1, __id2, __bv1, __bv2) \
1658 TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2)
1659
1660#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1661 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \
1662 __bv1, __bv2, __id1, __id2, __ev1, __ev2)
1663
1664#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \
1665 __eid1, __eid2, __ev1, __ev2) \
1666 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \
1667 __bv1, __bv2, __eid1, __eid2, __ev1, __ev2)
1668
1669static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1670 /* Numeric models ------------------ */
1671 /* FW MODEL BIOS VERS */
1672 TPV_QI0('I', 'M', '6', '5'), /* 570 */
1673 TPV_QI0('I', 'U', '2', '6'), /* 570E */
1674 TPV_QI0('I', 'B', '5', '4'), /* 600 */
1675 TPV_QI0('I', 'H', '4', '7'), /* 600E */
1676 TPV_QI0('I', 'N', '3', '6'), /* 600E */
1677 TPV_QI0('I', 'T', '5', '5'), /* 600X */
1678 TPV_QI0('I', 'D', '4', '8'), /* 770, 770E, 770ED */
1679 TPV_QI0('I', 'I', '4', '2'), /* 770X */
1680 TPV_QI0('I', 'O', '2', '3'), /* 770Z */
1681
1682 /* A-series ------------------------- */
1683 /* FW MODEL BIOS VERS EC VERS */
1684 TPV_QI0('I', 'W', '5', '9'), /* A20m */
1685 TPV_QI0('I', 'V', '6', '9'), /* A20p */
1686 TPV_QI0('1', '0', '2', '6'), /* A21e, A22e */
1687 TPV_QI0('K', 'U', '3', '6'), /* A21e */
1688 TPV_QI0('K', 'X', '3', '6'), /* A21m, A22m */
1689 TPV_QI0('K', 'Y', '3', '8'), /* A21p, A22p */
1690 TPV_QI0('1', 'B', '1', '7'), /* A22e */
1691 TPV_QI0('1', '3', '2', '0'), /* A22m */
1692 TPV_QI0('1', 'E', '7', '3'), /* A30/p (0) */
1693 TPV_QI1('1', 'G', '4', '1', '1', '7'), /* A31/p (0) */
1694 TPV_QI1('1', 'N', '1', '6', '0', '7'), /* A31/p (0) */
1695
1696 /* G-series ------------------------- */
1697 /* FW MODEL BIOS VERS */
1698 TPV_QI0('1', 'T', 'A', '6'), /* G40 */
1699 TPV_QI0('1', 'X', '5', '7'), /* G41 */
1700
1701 /* R-series, T-series --------------- */
1702 /* FW MODEL BIOS VERS EC VERS */
1703 TPV_QI0('1', 'C', 'F', '0'), /* R30 */
1704 TPV_QI0('1', 'F', 'F', '1'), /* R31 */
1705 TPV_QI0('1', 'M', '9', '7'), /* R32 */
1706 TPV_QI0('1', 'O', '6', '1'), /* R40 */
1707 TPV_QI0('1', 'P', '6', '5'), /* R40 */
1708 TPV_QI0('1', 'S', '7', '0'), /* R40e */
1709 TPV_QI1('1', 'R', 'D', 'R', '7', '1'), /* R50/p, R51,
1710 T40/p, T41/p, T42/p (1) */
1711 TPV_QI1('1', 'V', '7', '1', '2', '8'), /* R50e, R51 (1) */
1712 TPV_QI1('7', '8', '7', '1', '0', '6'), /* R51e (1) */
1713 TPV_QI1('7', '6', '6', '9', '1', '6'), /* R52 (1) */
1714 TPV_QI1('7', '0', '6', '9', '2', '8'), /* R52, T43 (1) */
1715
1716 TPV_QI0('I', 'Y', '6', '1'), /* T20 */
1717 TPV_QI0('K', 'Z', '3', '4'), /* T21 */
1718 TPV_QI0('1', '6', '3', '2'), /* T22 */
1719 TPV_QI1('1', 'A', '6', '4', '2', '3'), /* T23 (0) */
1720 TPV_QI1('1', 'I', '7', '1', '2', '0'), /* T30 (0) */
1721 TPV_QI1('1', 'Y', '6', '5', '2', '9'), /* T43/p (1) */
1722
1723 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */
1724 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */
1725 TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */
1726
1727 /* BIOS FW BIOS VERS EC FW EC VERS */
1728 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */
1729 TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'), /* T60/p wide */
1730
1731 /* X-series ------------------------- */
1732 /* FW MODEL BIOS VERS EC VERS */
1733 TPV_QI0('I', 'Z', '9', 'D'), /* X20, X21 */
1734 TPV_QI0('1', 'D', '7', '0'), /* X22, X23, X24 */
1735 TPV_QI1('1', 'K', '4', '8', '1', '8'), /* X30 (0) */
1736 TPV_QI1('1', 'Q', '9', '7', '2', '3'), /* X31, X32 (0) */
1737 TPV_QI1('1', 'U', 'D', '3', 'B', '2'), /* X40 (0) */
1738 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */
1739 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */
1740
1741 TPV_QL0('7', 'B', 'D', '7'), /* X60/s */
1742 TPV_QL0('7', 'J', '3', '0'), /* X60t */
1743
1744 /* (0) - older versions lack DMI EC fw string and functionality */
1745 /* (1) - older versions known to lack functionality */
1746};
1747
1748#undef TPV_QL1
1749#undef TPV_QL0
1750#undef TPV_QI2
1751#undef TPV_QI1
1752#undef TPV_QI0
1753#undef TPV_Q_X
1754#undef TPV_Q
1755
1756static void __init tpacpi_check_outdated_fw(void)
1757{
1758 unsigned long fwvers;
1759 u16 ec_version, bios_version;
1760
1761 fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable,
1762 ARRAY_SIZE(tpacpi_bios_version_qtable));
1763
1764 if (!fwvers)
1765 return;
1766
1767 bios_version = fwvers & 0xffffU;
1768 ec_version = (fwvers >> 16) & 0xffffU;
1769
1770 /* note that unknown versions are set to 0x0000 and we use that */
1771 if ((bios_version > thinkpad_id.bios_release) ||
1772 (ec_version > thinkpad_id.ec_release &&
1773 ec_version != TPACPI_MATCH_ANY)) {
1774 /*
1775 * The changelogs would let us track down the exact
1776 * reason, but it is just too much of a pain to track
1777 * it. We only list BIOSes that are either really
1778 * broken, or really stable to begin with, so it is
1779 * best if the user upgrades the firmware anyway.
1780 */
1781 printk(TPACPI_WARN
1782 "WARNING: Outdated ThinkPad BIOS/EC firmware\n");
1783 printk(TPACPI_WARN
1784 "WARNING: This firmware may be missing critical bug "
1785 "fixes and/or important features\n");
1786 }
1787}
1788
1789static bool __init tpacpi_is_fw_known(void)
1790{
1791 return tpacpi_check_quirks(tpacpi_bios_version_qtable,
1792 ARRAY_SIZE(tpacpi_bios_version_qtable)) != 0;
1793}
1794
1604/**************************************************************************** 1795/****************************************************************************
1605 **************************************************************************** 1796 ****************************************************************************
1606 * 1797 *
@@ -1634,6 +1825,7 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1634 (thinkpad_id.nummodel_str) ? 1825 (thinkpad_id.nummodel_str) ?
1635 thinkpad_id.nummodel_str : "unknown"); 1826 thinkpad_id.nummodel_str : "unknown");
1636 1827
1828 tpacpi_check_outdated_fw();
1637 return 0; 1829 return 0;
1638} 1830}
1639 1831
@@ -1731,16 +1923,42 @@ struct tp_nvram_state {
1731 u8 volume_level; 1923 u8 volume_level;
1732}; 1924};
1733 1925
1926/* kthread for the hotkey poller */
1734static struct task_struct *tpacpi_hotkey_task; 1927static struct task_struct *tpacpi_hotkey_task;
1735static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ 1928
1736static int hotkey_poll_freq = 10; /* Hz */ 1929/* Acquired while the poller kthread is running, use to sync start/stop */
1737static struct mutex hotkey_thread_mutex; 1930static struct mutex hotkey_thread_mutex;
1931
1932/*
1933 * Acquire mutex to write poller control variables.
1934 * Increment hotkey_config_change when changing them.
1935 *
1936 * See HOTKEY_CONFIG_CRITICAL_START/HOTKEY_CONFIG_CRITICAL_END
1937 */
1738static struct mutex hotkey_thread_data_mutex; 1938static struct mutex hotkey_thread_data_mutex;
1739static unsigned int hotkey_config_change; 1939static unsigned int hotkey_config_change;
1740 1940
1941/*
1942 * hotkey poller control variables
1943 *
1944 * Must be atomic or readers will also need to acquire mutex
1945 */
1946static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */
1947static unsigned int hotkey_poll_freq = 10; /* Hz */
1948
1949#define HOTKEY_CONFIG_CRITICAL_START \
1950 do { \
1951 mutex_lock(&hotkey_thread_data_mutex); \
1952 hotkey_config_change++; \
1953 } while (0);
1954#define HOTKEY_CONFIG_CRITICAL_END \
1955 mutex_unlock(&hotkey_thread_data_mutex);
1956
1741#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 1957#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1742 1958
1743#define hotkey_source_mask 0U 1959#define hotkey_source_mask 0U
1960#define HOTKEY_CONFIG_CRITICAL_START
1961#define HOTKEY_CONFIG_CRITICAL_END
1744 1962
1745#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 1963#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1746 1964
@@ -1765,19 +1983,6 @@ static u16 *hotkey_keycode_map;
1765 1983
1766static struct attribute_set *hotkey_dev_attributes; 1984static struct attribute_set *hotkey_dev_attributes;
1767 1985
1768#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
1769#define HOTKEY_CONFIG_CRITICAL_START \
1770 do { \
1771 mutex_lock(&hotkey_thread_data_mutex); \
1772 hotkey_config_change++; \
1773 } while (0);
1774#define HOTKEY_CONFIG_CRITICAL_END \
1775 mutex_unlock(&hotkey_thread_data_mutex);
1776#else
1777#define HOTKEY_CONFIG_CRITICAL_START
1778#define HOTKEY_CONFIG_CRITICAL_END
1779#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
1780
1781/* HKEY.MHKG() return bits */ 1986/* HKEY.MHKG() return bits */
1782#define TP_HOTKEY_TABLET_MASK (1 << 3) 1987#define TP_HOTKEY_TABLET_MASK (1 << 3)
1783 1988
@@ -1822,7 +2027,9 @@ static int hotkey_mask_get(void)
1822 if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) 2027 if (!acpi_evalf(hkey_handle, &m, "DHKN", "d"))
1823 return -EIO; 2028 return -EIO;
1824 } 2029 }
2030 HOTKEY_CONFIG_CRITICAL_START
1825 hotkey_mask = m | (hotkey_source_mask & hotkey_mask); 2031 hotkey_mask = m | (hotkey_source_mask & hotkey_mask);
2032 HOTKEY_CONFIG_CRITICAL_END
1826 2033
1827 return 0; 2034 return 0;
1828} 2035}
@@ -2075,6 +2282,7 @@ static int hotkey_kthread(void *data)
2075 unsigned int si, so; 2282 unsigned int si, so;
2076 unsigned long t; 2283 unsigned long t;
2077 unsigned int change_detector, must_reset; 2284 unsigned int change_detector, must_reset;
2285 unsigned int poll_freq;
2078 2286
2079 mutex_lock(&hotkey_thread_mutex); 2287 mutex_lock(&hotkey_thread_mutex);
2080 2288
@@ -2091,12 +2299,17 @@ static int hotkey_kthread(void *data)
2091 mutex_lock(&hotkey_thread_data_mutex); 2299 mutex_lock(&hotkey_thread_data_mutex);
2092 change_detector = hotkey_config_change; 2300 change_detector = hotkey_config_change;
2093 mask = hotkey_source_mask & hotkey_mask; 2301 mask = hotkey_source_mask & hotkey_mask;
2302 poll_freq = hotkey_poll_freq;
2094 mutex_unlock(&hotkey_thread_data_mutex); 2303 mutex_unlock(&hotkey_thread_data_mutex);
2095 hotkey_read_nvram(&s[so], mask); 2304 hotkey_read_nvram(&s[so], mask);
2096 2305
2097 while (!kthread_should_stop() && hotkey_poll_freq) { 2306 while (!kthread_should_stop()) {
2098 if (t == 0) 2307 if (t == 0) {
2099 t = 1000/hotkey_poll_freq; 2308 if (likely(poll_freq))
2309 t = 1000/poll_freq;
2310 else
2311 t = 100; /* should never happen... */
2312 }
2100 t = msleep_interruptible(t); 2313 t = msleep_interruptible(t);
2101 if (unlikely(kthread_should_stop())) 2314 if (unlikely(kthread_should_stop()))
2102 break; 2315 break;
@@ -2112,6 +2325,7 @@ static int hotkey_kthread(void *data)
2112 change_detector = hotkey_config_change; 2325 change_detector = hotkey_config_change;
2113 } 2326 }
2114 mask = hotkey_source_mask & hotkey_mask; 2327 mask = hotkey_source_mask & hotkey_mask;
2328 poll_freq = hotkey_poll_freq;
2115 mutex_unlock(&hotkey_thread_data_mutex); 2329 mutex_unlock(&hotkey_thread_data_mutex);
2116 2330
2117 if (likely(mask)) { 2331 if (likely(mask)) {
@@ -2131,6 +2345,7 @@ exit:
2131 return 0; 2345 return 0;
2132} 2346}
2133 2347
2348/* call with hotkey_mutex held */
2134static void hotkey_poll_stop_sync(void) 2349static void hotkey_poll_stop_sync(void)
2135{ 2350{
2136 if (tpacpi_hotkey_task) { 2351 if (tpacpi_hotkey_task) {
@@ -2147,10 +2362,11 @@ static void hotkey_poll_stop_sync(void)
2147} 2362}
2148 2363
2149/* call with hotkey_mutex held */ 2364/* call with hotkey_mutex held */
2150static void hotkey_poll_setup(int may_warn) 2365static void hotkey_poll_setup(bool may_warn)
2151{ 2366{
2152 if ((hotkey_source_mask & hotkey_mask) != 0 && 2367 u32 hotkeys_to_poll = hotkey_source_mask & hotkey_mask;
2153 hotkey_poll_freq > 0 && 2368
2369 if (hotkeys_to_poll != 0 && hotkey_poll_freq > 0 &&
2154 (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { 2370 (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
2155 if (!tpacpi_hotkey_task) { 2371 if (!tpacpi_hotkey_task) {
2156 tpacpi_hotkey_task = kthread_run(hotkey_kthread, 2372 tpacpi_hotkey_task = kthread_run(hotkey_kthread,
@@ -2164,26 +2380,37 @@ static void hotkey_poll_setup(int may_warn)
2164 } 2380 }
2165 } else { 2381 } else {
2166 hotkey_poll_stop_sync(); 2382 hotkey_poll_stop_sync();
2167 if (may_warn && 2383 if (may_warn && hotkeys_to_poll != 0 &&
2168 hotkey_source_mask != 0 && hotkey_poll_freq == 0) { 2384 hotkey_poll_freq == 0) {
2169 printk(TPACPI_NOTICE 2385 printk(TPACPI_NOTICE
2170 "hot keys 0x%08x require polling, " 2386 "hot keys 0x%08x require polling, "
2171 "which is currently disabled\n", 2387 "which is currently disabled\n",
2172 hotkey_source_mask); 2388 hotkeys_to_poll);
2173 } 2389 }
2174 } 2390 }
2175} 2391}
2176 2392
2177static void hotkey_poll_setup_safe(int may_warn) 2393static void hotkey_poll_setup_safe(bool may_warn)
2178{ 2394{
2179 mutex_lock(&hotkey_mutex); 2395 mutex_lock(&hotkey_mutex);
2180 hotkey_poll_setup(may_warn); 2396 hotkey_poll_setup(may_warn);
2181 mutex_unlock(&hotkey_mutex); 2397 mutex_unlock(&hotkey_mutex);
2182} 2398}
2183 2399
2400/* call with hotkey_mutex held */
2401static void hotkey_poll_set_freq(unsigned int freq)
2402{
2403 if (!freq)
2404 hotkey_poll_stop_sync();
2405
2406 HOTKEY_CONFIG_CRITICAL_START
2407 hotkey_poll_freq = freq;
2408 HOTKEY_CONFIG_CRITICAL_END
2409}
2410
2184#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 2411#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
2185 2412
2186static void hotkey_poll_setup_safe(int __unused) 2413static void hotkey_poll_setup_safe(bool __unused)
2187{ 2414{
2188} 2415}
2189 2416
@@ -2201,7 +2428,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2201 case TPACPI_LIFE_EXITING: 2428 case TPACPI_LIFE_EXITING:
2202 return -EBUSY; 2429 return -EBUSY;
2203 case TPACPI_LIFE_RUNNING: 2430 case TPACPI_LIFE_RUNNING:
2204 hotkey_poll_setup_safe(0); 2431 hotkey_poll_setup_safe(false);
2205 return 0; 2432 return 0;
2206 } 2433 }
2207 2434
@@ -2214,7 +2441,7 @@ static void hotkey_inputdev_close(struct input_dev *dev)
2214{ 2441{
2215 /* disable hotkey polling when possible */ 2442 /* disable hotkey polling when possible */
2216 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) 2443 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING)
2217 hotkey_poll_setup_safe(0); 2444 hotkey_poll_setup_safe(false);
2218} 2445}
2219 2446
2220/* sysfs hotkey enable ------------------------------------------------- */ 2447/* sysfs hotkey enable ------------------------------------------------- */
@@ -2288,7 +2515,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
2288 res = hotkey_mask_set(t); 2515 res = hotkey_mask_set(t);
2289 2516
2290#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL 2517#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2291 hotkey_poll_setup(1); 2518 hotkey_poll_setup(true);
2292#endif 2519#endif
2293 2520
2294 mutex_unlock(&hotkey_mutex); 2521 mutex_unlock(&hotkey_mutex);
@@ -2318,6 +2545,8 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
2318 struct device_attribute *attr, 2545 struct device_attribute *attr,
2319 char *buf) 2546 char *buf)
2320{ 2547{
2548 printk_deprecated_attribute("hotkey_bios_mask",
2549 "This attribute is useless.");
2321 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); 2550 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
2322} 2551}
2323 2552
@@ -2377,7 +2606,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
2377 hotkey_source_mask = t; 2606 hotkey_source_mask = t;
2378 HOTKEY_CONFIG_CRITICAL_END 2607 HOTKEY_CONFIG_CRITICAL_END
2379 2608
2380 hotkey_poll_setup(1); 2609 hotkey_poll_setup(true);
2610 hotkey_mask_set(hotkey_mask);
2381 2611
2382 mutex_unlock(&hotkey_mutex); 2612 mutex_unlock(&hotkey_mutex);
2383 2613
@@ -2410,9 +2640,9 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
2410 if (mutex_lock_killable(&hotkey_mutex)) 2640 if (mutex_lock_killable(&hotkey_mutex))
2411 return -ERESTARTSYS; 2641 return -ERESTARTSYS;
2412 2642
2413 hotkey_poll_freq = t; 2643 hotkey_poll_set_freq(t);
2644 hotkey_poll_setup(true);
2414 2645
2415 hotkey_poll_setup(1);
2416 mutex_unlock(&hotkey_mutex); 2646 mutex_unlock(&hotkey_mutex);
2417 2647
2418 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); 2648 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
@@ -2603,7 +2833,9 @@ static void tpacpi_send_radiosw_update(void)
2603static void hotkey_exit(void) 2833static void hotkey_exit(void)
2604{ 2834{
2605#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL 2835#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2836 mutex_lock(&hotkey_mutex);
2606 hotkey_poll_stop_sync(); 2837 hotkey_poll_stop_sync();
2838 mutex_unlock(&hotkey_mutex);
2607#endif 2839#endif
2608 2840
2609 if (hotkey_dev_attributes) 2841 if (hotkey_dev_attributes)
@@ -2623,6 +2855,15 @@ static void hotkey_exit(void)
2623 } 2855 }
2624} 2856}
2625 2857
2858static void __init hotkey_unmap(const unsigned int scancode)
2859{
2860 if (hotkey_keycode_map[scancode] != KEY_RESERVED) {
2861 clear_bit(hotkey_keycode_map[scancode],
2862 tpacpi_inputdev->keybit);
2863 hotkey_keycode_map[scancode] = KEY_RESERVED;
2864 }
2865}
2866
2626static int __init hotkey_init(struct ibm_init_struct *iibm) 2867static int __init hotkey_init(struct ibm_init_struct *iibm)
2627{ 2868{
2628 /* Requirements for changing the default keymaps: 2869 /* Requirements for changing the default keymaps:
@@ -2701,11 +2942,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2701 KEY_UNKNOWN, /* 0x0D: FN+INSERT */ 2942 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
2702 KEY_UNKNOWN, /* 0x0E: FN+DELETE */ 2943 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
2703 2944
2704 /* These either have to go through ACPI video, or 2945 /* These should be enabled --only-- when ACPI video
2705 * act like in the IBM ThinkPads, so don't ever 2946 * is disabled (i.e. in "vendor" mode), and are handled
2706 * enable them by default */ 2947 * in a special way by the init code */
2707 KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ 2948 KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
2708 KEY_RESERVED, /* 0x10: FN+END (brightness down) */ 2949 KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
2709 2950
2710 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ 2951 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
2711 2952
@@ -2831,19 +3072,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2831 goto err_exit; 3072 goto err_exit;
2832 } 3073 }
2833 3074
2834#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2835 if (tp_features.hotkey_mask) {
2836 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
2837 & ~hotkey_all_mask;
2838 } else {
2839 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
2840 }
2841
2842 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2843 "hotkey source mask 0x%08x, polling freq %d\n",
2844 hotkey_source_mask, hotkey_poll_freq);
2845#endif
2846
2847#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3075#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2848 if (dbg_wlswemul) { 3076 if (dbg_wlswemul) {
2849 tp_features.hotkey_wlsw = 1; 3077 tp_features.hotkey_wlsw = 1;
@@ -2944,17 +3172,31 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2944 "Disabling thinkpad-acpi brightness events " 3172 "Disabling thinkpad-acpi brightness events "
2945 "by default...\n"); 3173 "by default...\n");
2946 3174
2947 /* The hotkey_reserved_mask change below is not 3175 /* Disable brightness up/down on Lenovo thinkpads when
2948 * necessary while the keys are at KEY_RESERVED in the 3176 * ACPI is handling them, otherwise it is plain impossible
2949 * default map, but better safe than sorry, leave it 3177 * for userspace to do something even remotely sane */
2950 * here as a marker of what we have to do, especially
2951 * when we finally become able to set this at runtime
2952 * on response to X.org requests */
2953 hotkey_reserved_mask |= 3178 hotkey_reserved_mask |=
2954 (1 << TP_ACPI_HOTKEYSCAN_FNHOME) 3179 (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
2955 | (1 << TP_ACPI_HOTKEYSCAN_FNEND); 3180 | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
3181 hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNHOME);
3182 hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNEND);
2956 } 3183 }
2957 3184
3185#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
3186 if (tp_features.hotkey_mask) {
3187 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
3188 & ~hotkey_all_mask
3189 & ~hotkey_reserved_mask;
3190 } else {
3191 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
3192 & ~hotkey_reserved_mask;
3193 }
3194
3195 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3196 "hotkey source mask 0x%08x, polling freq %u\n",
3197 hotkey_source_mask, hotkey_poll_freq);
3198#endif
3199
2958 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3200 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2959 "enabling firmware HKEY event interface...\n"); 3201 "enabling firmware HKEY event interface...\n");
2960 res = hotkey_status_set(true); 3202 res = hotkey_status_set(true);
@@ -2978,7 +3220,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2978 tpacpi_inputdev->open = &hotkey_inputdev_open; 3220 tpacpi_inputdev->open = &hotkey_inputdev_open;
2979 tpacpi_inputdev->close = &hotkey_inputdev_close; 3221 tpacpi_inputdev->close = &hotkey_inputdev_close;
2980 3222
2981 hotkey_poll_setup_safe(1); 3223 hotkey_poll_setup_safe(true);
2982 tpacpi_send_radiosw_update(); 3224 tpacpi_send_radiosw_update();
2983 tpacpi_input_send_tabletsw(); 3225 tpacpi_input_send_tabletsw();
2984 3226
@@ -3266,7 +3508,7 @@ static void hotkey_resume(void)
3266 hotkey_tablet_mode_notify_change(); 3508 hotkey_tablet_mode_notify_change();
3267 hotkey_wakeup_reason_notify_change(); 3509 hotkey_wakeup_reason_notify_change();
3268 hotkey_wakeup_hotunplug_complete_notify_change(); 3510 hotkey_wakeup_hotunplug_complete_notify_change();
3269 hotkey_poll_setup_safe(0); 3511 hotkey_poll_setup_safe(false);
3270} 3512}
3271 3513
3272/* procfs -------------------------------------------------------------- */ 3514/* procfs -------------------------------------------------------------- */
@@ -3338,7 +3580,8 @@ static int hotkey_write(char *buf)
3338 hotkey_enabledisable_warn(0); 3580 hotkey_enabledisable_warn(0);
3339 res = -EPERM; 3581 res = -EPERM;
3340 } else if (strlencmp(cmd, "reset") == 0) { 3582 } else if (strlencmp(cmd, "reset") == 0) {
3341 mask = hotkey_orig_mask; 3583 mask = (hotkey_all_mask | hotkey_source_mask)
3584 & ~hotkey_reserved_mask;
3342 } else if (sscanf(cmd, "0x%x", &mask) == 1) { 3585 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
3343 /* mask set */ 3586 /* mask set */
3344 } else if (sscanf(cmd, "%x", &mask) == 1) { 3587 } else if (sscanf(cmd, "%x", &mask) == 1) {
@@ -5655,16 +5898,16 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
5655 /* Models with ATI GPUs known to require ECNVRAM mode */ 5898 /* Models with ATI GPUs known to require ECNVRAM mode */
5656 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ 5899 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
5657 5900
5658 /* Models with ATI GPUs (waiting confirmation) */ 5901 /* Models with ATI GPUs that can use ECNVRAM */
5659 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 5902 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
5660 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 5903 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5661 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 5904 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5662 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 5905 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5663 5906
5664 /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ 5907 /* Models with Intel Extreme Graphics 2 */
5908 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
5665 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 5909 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5666 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 5910 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5667 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5668 5911
5669 /* Models with Intel GMA900 */ 5912 /* Models with Intel GMA900 */
5670 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ 5913 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@@ -7524,9 +7767,11 @@ static int __init probe_for_thinkpad(void)
7524 7767
7525 /* 7768 /*
7526 * Non-ancient models have better DMI tagging, but very old models 7769 * Non-ancient models have better DMI tagging, but very old models
7527 * don't. 7770 * don't. tpacpi_is_fw_known() is a cheat to help in that case.
7528 */ 7771 */
7529 is_thinkpad = (thinkpad_id.model_str != NULL); 7772 is_thinkpad = (thinkpad_id.model_str != NULL) ||
7773 (thinkpad_id.ec_model != 0) ||
7774 tpacpi_is_fw_known();
7530 7775
7531 /* ec is required because many other handles are relative to it */ 7776 /* ec is required because many other handles are relative to it */
7532 TPACPI_ACPIHANDLE_INIT(ec); 7777 TPACPI_ACPIHANDLE_INIT(ec);
@@ -7537,13 +7782,6 @@ static int __init probe_for_thinkpad(void)
7537 return -ENODEV; 7782 return -ENODEV;
7538 } 7783 }
7539 7784
7540 /*
7541 * Risks a regression on very old machines, but reduces potential
7542 * false positives a damn great deal
7543 */
7544 if (!is_thinkpad)
7545 is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);
7546
7547 if (!is_thinkpad && !force_load) 7785 if (!is_thinkpad && !force_load)
7548 return -ENODEV; 7786 return -ENODEV;
7549 7787