aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/thinkpad_acpi.c207
-rw-r--r--drivers/misc/thinkpad_acpi.h37
2 files changed, 191 insertions, 53 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 0222bbaf7b76..37891a8c030a 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -22,7 +22,7 @@
22 */ 22 */
23 23
24#define IBM_VERSION "0.16" 24#define IBM_VERSION "0.16"
25#define TPACPI_SYSFS_VERSION 0x010000 25#define TPACPI_SYSFS_VERSION 0x020000
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -117,6 +117,12 @@ IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
117 117
118#define __unused __attribute__ ((unused)) 118#define __unused __attribute__ ((unused))
119 119
120static enum {
121 TPACPI_LIFE_INIT = 0,
122 TPACPI_LIFE_RUNNING,
123 TPACPI_LIFE_EXITING,
124} tpacpi_lifecycle;
125
120/**************************************************************************** 126/****************************************************************************
121 **************************************************************************** 127 ****************************************************************************
122 * 128 *
@@ -342,6 +348,9 @@ static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
342{ 348{
343 struct ibm_struct *ibm = data; 349 struct ibm_struct *ibm = data;
344 350
351 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
352 return;
353
345 if (!ibm || !ibm->acpi || !ibm->acpi->notify) 354 if (!ibm || !ibm->acpi || !ibm->acpi->notify)
346 return; 355 return;
347 356
@@ -517,8 +526,10 @@ static char *next_cmd(char **cmds)
517 ****************************************************************************/ 526 ****************************************************************************/
518 527
519static struct platform_device *tpacpi_pdev; 528static struct platform_device *tpacpi_pdev;
529static struct platform_device *tpacpi_sensors_pdev;
520static struct class_device *tpacpi_hwmon; 530static struct class_device *tpacpi_hwmon;
521static struct input_dev *tpacpi_inputdev; 531static struct input_dev *tpacpi_inputdev;
532static struct mutex tpacpi_inputdev_send_mutex;
522 533
523 534
524static int tpacpi_resume_handler(struct platform_device *pdev) 535static int tpacpi_resume_handler(struct platform_device *pdev)
@@ -543,6 +554,12 @@ static struct platform_driver tpacpi_pdriver = {
543 .resume = tpacpi_resume_handler, 554 .resume = tpacpi_resume_handler,
544}; 555};
545 556
557static struct platform_driver tpacpi_hwmon_pdriver = {
558 .driver = {
559 .name = IBM_HWMON_DRVR_NAME,
560 .owner = THIS_MODULE,
561 },
562};
546 563
547/************************************************************************* 564/*************************************************************************
548 * thinkpad-acpi driver attributes 565 * thinkpad-acpi driver attributes
@@ -692,6 +709,8 @@ static int parse_strtoul(const char *buf,
692{ 709{
693 char *endp; 710 char *endp;
694 711
712 while (*buf && isspace(*buf))
713 buf++;
695 *value = simple_strtoul(buf, &endp, 0); 714 *value = simple_strtoul(buf, &endp, 0);
696 while (*endp && isspace(*endp)) 715 while (*endp && isspace(*endp))
697 endp++; 716 endp++;
@@ -989,6 +1008,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
989 1008
990 int res, i; 1009 int res, i;
991 int status; 1010 int status;
1011 int hkeyv;
992 1012
993 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 1013 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
994 1014
@@ -1014,18 +1034,35 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
1014 return res; 1034 return res;
1015 1035
1016 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 1036 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
1017 A30, R30, R31, T20-22, X20-21, X22-24 */ 1037 A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
1018 tp_features.hotkey_mask = 1038 for HKEY interface version 0x100 */
1019 acpi_evalf(hkey_handle, NULL, "DHKN", "qv"); 1039 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
1040 if ((hkeyv >> 8) != 1) {
1041 printk(IBM_ERR "unknown version of the "
1042 "HKEY interface: 0x%x\n", hkeyv);
1043 printk(IBM_ERR "please report this to %s\n",
1044 IBM_MAIL);
1045 } else {
1046 /*
1047 * MHKV 0x100 in A31, R40, R40e,
1048 * T4x, X31, and later
1049 * */
1050 tp_features.hotkey_mask = 1;
1051 }
1052 }
1020 1053
1021 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 1054 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
1022 str_supported(tp_features.hotkey_mask)); 1055 str_supported(tp_features.hotkey_mask));
1023 1056
1024 if (tp_features.hotkey_mask) { 1057 if (tp_features.hotkey_mask) {
1025 /* MHKA available in A31, R40, R40e, T4x, X31, and later */
1026 if (!acpi_evalf(hkey_handle, &hotkey_all_mask, 1058 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
1027 "MHKA", "qd")) 1059 "MHKA", "qd")) {
1060 printk(IBM_ERR
1061 "missing MHKA handler, "
1062 "please report this to %s\n",
1063 IBM_MAIL);
1028 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ 1064 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
1065 }
1029 } 1066 }
1030 1067
1031 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); 1068 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
@@ -1131,6 +1168,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
1131 unsigned int keycode) 1168 unsigned int keycode)
1132{ 1169{
1133 if (keycode != KEY_RESERVED) { 1170 if (keycode != KEY_RESERVED) {
1171 mutex_lock(&tpacpi_inputdev_send_mutex);
1172
1134 input_report_key(tpacpi_inputdev, keycode, 1); 1173 input_report_key(tpacpi_inputdev, keycode, 1);
1135 if (keycode == KEY_UNKNOWN) 1174 if (keycode == KEY_UNKNOWN)
1136 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 1175 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
@@ -1142,6 +1181,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
1142 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 1181 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1143 scancode); 1182 scancode);
1144 input_sync(tpacpi_inputdev); 1183 input_sync(tpacpi_inputdev);
1184
1185 mutex_unlock(&tpacpi_inputdev_send_mutex);
1145 } 1186 }
1146} 1187}
1147 1188
@@ -1149,18 +1190,47 @@ static void tpacpi_input_send_radiosw(void)
1149{ 1190{
1150 int wlsw; 1191 int wlsw;
1151 1192
1152 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) 1193 mutex_lock(&tpacpi_inputdev_send_mutex);
1194
1195 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
1153 input_report_switch(tpacpi_inputdev, 1196 input_report_switch(tpacpi_inputdev,
1154 SW_RADIO, !!wlsw); 1197 SW_RADIO, !!wlsw);
1198 input_sync(tpacpi_inputdev);
1199 }
1200
1201 mutex_unlock(&tpacpi_inputdev_send_mutex);
1155} 1202}
1156 1203
1157static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1204static void hotkey_notify(struct ibm_struct *ibm, u32 event)
1158{ 1205{
1159 u32 hkey; 1206 u32 hkey;
1160 unsigned int keycode, scancode; 1207 unsigned int keycode, scancode;
1161 int send_acpi_ev = 0; 1208 int send_acpi_ev;
1209 int ignore_acpi_ev;
1210
1211 if (event != 0x80) {
1212 printk(IBM_ERR "unknown HKEY notification event %d\n", event);
1213 /* forward it to userspace, maybe it knows how to handle it */
1214 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1215 ibm->acpi->device->dev.bus_id,
1216 event, 0);
1217 return;
1218 }
1219
1220 while (1) {
1221 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1222 printk(IBM_ERR "failed to retrieve HKEY event\n");
1223 return;
1224 }
1225
1226 if (hkey == 0) {
1227 /* queue empty */
1228 return;
1229 }
1230
1231 send_acpi_ev = 0;
1232 ignore_acpi_ev = 0;
1162 1233
1163 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1164 switch (hkey >> 12) { 1234 switch (hkey >> 12) {
1165 case 1: 1235 case 1:
1166 /* 0x1000-0x1FFF: key presses */ 1236 /* 0x1000-0x1FFF: key presses */
@@ -1182,9 +1252,11 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
1182 * eat up known LID events */ 1252 * eat up known LID events */
1183 if (hkey != 0x5001 && hkey != 0x5002) { 1253 if (hkey != 0x5001 && hkey != 0x5002) {
1184 printk(IBM_ERR 1254 printk(IBM_ERR
1185 "unknown LID-related hotkey event: 0x%04x\n", 1255 "unknown LID-related HKEY event: 0x%04x\n",
1186 hkey); 1256 hkey);
1187 send_acpi_ev = 1; 1257 send_acpi_ev = 1;
1258 } else {
1259 ignore_acpi_ev = 1;
1188 } 1260 }
1189 break; 1261 break;
1190 case 7: 1262 case 7:
@@ -1202,21 +1274,18 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
1202 printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey); 1274 printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
1203 send_acpi_ev = 1; 1275 send_acpi_ev = 1;
1204 } 1276 }
1205 } else {
1206 printk(IBM_ERR "unknown hotkey notification event %d\n", event);
1207 hkey = 0;
1208 send_acpi_ev = 1;
1209 }
1210 1277
1211 /* Legacy events */ 1278 /* Legacy events */
1212 if (send_acpi_ev || hotkey_report_mode < 2) 1279 if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) {
1213 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); 1280 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
1281 }
1214 1282
1215 /* netlink events */ 1283 /* netlink events */
1216 if (send_acpi_ev) { 1284 if (!ignore_acpi_ev && send_acpi_ev) {
1217 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, 1285 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1218 ibm->acpi->device->dev.bus_id, 1286 ibm->acpi->device->dev.bus_id,
1219 event, hkey); 1287 event, hkey);
1288 }
1220 } 1289 }
1221} 1290}
1222 1291
@@ -2812,7 +2881,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2812 2881
2813 switch(thermal_read_mode) { 2882 switch(thermal_read_mode) {
2814 case TPACPI_THERMAL_TPEC_16: 2883 case TPACPI_THERMAL_TPEC_16:
2815 res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2884 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2816 &thermal_temp_input16_group); 2885 &thermal_temp_input16_group);
2817 if (res) 2886 if (res)
2818 return res; 2887 return res;
@@ -2820,7 +2889,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2820 case TPACPI_THERMAL_TPEC_8: 2889 case TPACPI_THERMAL_TPEC_8:
2821 case TPACPI_THERMAL_ACPI_TMP07: 2890 case TPACPI_THERMAL_ACPI_TMP07:
2822 case TPACPI_THERMAL_ACPI_UPDT: 2891 case TPACPI_THERMAL_ACPI_UPDT:
2823 res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2892 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2824 &thermal_temp_input8_group); 2893 &thermal_temp_input8_group);
2825 if (res) 2894 if (res)
2826 return res; 2895 return res;
@@ -2837,13 +2906,13 @@ static void thermal_exit(void)
2837{ 2906{
2838 switch(thermal_read_mode) { 2907 switch(thermal_read_mode) {
2839 case TPACPI_THERMAL_TPEC_16: 2908 case TPACPI_THERMAL_TPEC_16:
2840 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2909 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2841 &thermal_temp_input16_group); 2910 &thermal_temp_input16_group);
2842 break; 2911 break;
2843 case TPACPI_THERMAL_TPEC_8: 2912 case TPACPI_THERMAL_TPEC_8:
2844 case TPACPI_THERMAL_ACPI_TMP07: 2913 case TPACPI_THERMAL_ACPI_TMP07:
2845 case TPACPI_THERMAL_ACPI_UPDT: 2914 case TPACPI_THERMAL_ACPI_UPDT:
2846 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2915 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2847 &thermal_temp_input16_group); 2916 &thermal_temp_input16_group);
2848 break; 2917 break;
2849 case TPACPI_THERMAL_NONE: 2918 case TPACPI_THERMAL_NONE:
@@ -3626,7 +3695,7 @@ static struct device_attribute dev_attr_fan_fan1_input =
3626 __ATTR(fan1_input, S_IRUGO, 3695 __ATTR(fan1_input, S_IRUGO,
3627 fan_fan1_input_show, NULL); 3696 fan_fan1_input_show, NULL);
3628 3697
3629/* sysfs fan fan_watchdog (driver) ------------------------------------- */ 3698/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */
3630static ssize_t fan_fan_watchdog_show(struct device_driver *drv, 3699static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
3631 char *buf) 3700 char *buf)
3632{ 3701{
@@ -3768,10 +3837,10 @@ static int __init fan_init(struct ibm_init_struct *iibm)
3768 3837
3769 if (fan_status_access_mode != TPACPI_FAN_NONE || 3838 if (fan_status_access_mode != TPACPI_FAN_NONE ||
3770 fan_control_access_mode != TPACPI_FAN_WR_NONE) { 3839 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
3771 rc = sysfs_create_group(&tpacpi_pdev->dev.kobj, 3840 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
3772 &fan_attr_group); 3841 &fan_attr_group);
3773 if (!(rc < 0)) 3842 if (!(rc < 0))
3774 rc = driver_create_file(&tpacpi_pdriver.driver, 3843 rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
3775 &driver_attr_fan_watchdog); 3844 &driver_attr_fan_watchdog);
3776 if (rc < 0) 3845 if (rc < 0)
3777 return rc; 3846 return rc;
@@ -3854,8 +3923,8 @@ static void fan_exit(void)
3854 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n"); 3923 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
3855 3924
3856 /* FIXME: can we really do this unconditionally? */ 3925 /* FIXME: can we really do this unconditionally? */
3857 sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group); 3926 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
3858 driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog); 3927 driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog);
3859 3928
3860 cancel_delayed_work(&fan_watchdog_task); 3929 cancel_delayed_work(&fan_watchdog_task);
3861 flush_scheduled_work(); 3930 flush_scheduled_work();
@@ -3888,6 +3957,9 @@ static void fan_watchdog_fire(struct work_struct *ignored)
3888{ 3957{
3889 int rc; 3958 int rc;
3890 3959
3960 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
3961 return;
3962
3891 printk(IBM_NOTICE "fan watchdog: enabling fan\n"); 3963 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
3892 rc = fan_set_enable(); 3964 rc = fan_set_enable();
3893 if (rc < 0) { 3965 if (rc < 0) {
@@ -3908,7 +3980,8 @@ static void fan_watchdog_reset(void)
3908 if (fan_watchdog_active) 3980 if (fan_watchdog_active)
3909 cancel_delayed_work(&fan_watchdog_task); 3981 cancel_delayed_work(&fan_watchdog_task);
3910 3982
3911 if (fan_watchdog_maxinterval > 0) { 3983 if (fan_watchdog_maxinterval > 0 &&
3984 tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
3912 fan_watchdog_active = 1; 3985 fan_watchdog_active = 1;
3913 if (!schedule_delayed_work(&fan_watchdog_task, 3986 if (!schedule_delayed_work(&fan_watchdog_task,
3914 msecs_to_jiffies(fan_watchdog_maxinterval 3987 msecs_to_jiffies(fan_watchdog_maxinterval
@@ -4302,6 +4375,19 @@ static struct ibm_struct fan_driver_data = {
4302 **************************************************************************** 4375 ****************************************************************************
4303 ****************************************************************************/ 4376 ****************************************************************************/
4304 4377
4378/* sysfs name ---------------------------------------------------------- */
4379static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
4380 struct device_attribute *attr,
4381 char *buf)
4382{
4383 return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME);
4384}
4385
4386static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
4387 __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
4388
4389/* --------------------------------------------------------------------- */
4390
4305/* /proc support */ 4391/* /proc support */
4306static struct proc_dir_entry *proc_dir; 4392static struct proc_dir_entry *proc_dir;
4307 4393
@@ -4674,6 +4760,8 @@ static int __init thinkpad_acpi_module_init(void)
4674{ 4760{
4675 int ret, i; 4761 int ret, i;
4676 4762
4763 tpacpi_lifecycle = TPACPI_LIFE_INIT;
4764
4677 /* Parameter checking */ 4765 /* Parameter checking */
4678 if (hotkey_report_mode > 2) 4766 if (hotkey_report_mode > 2)
4679 return -EINVAL; 4767 return -EINVAL;
@@ -4702,19 +4790,31 @@ static int __init thinkpad_acpi_module_init(void)
4702 4790
4703 ret = platform_driver_register(&tpacpi_pdriver); 4791 ret = platform_driver_register(&tpacpi_pdriver);
4704 if (ret) { 4792 if (ret) {
4705 printk(IBM_ERR "unable to register platform driver\n"); 4793 printk(IBM_ERR "unable to register main platform driver\n");
4706 thinkpad_acpi_module_exit(); 4794 thinkpad_acpi_module_exit();
4707 return ret; 4795 return ret;
4708 } 4796 }
4709 tp_features.platform_drv_registered = 1; 4797 tp_features.platform_drv_registered = 1;
4710 4798
4799 ret = platform_driver_register(&tpacpi_hwmon_pdriver);
4800 if (ret) {
4801 printk(IBM_ERR "unable to register hwmon platform driver\n");
4802 thinkpad_acpi_module_exit();
4803 return ret;
4804 }
4805 tp_features.sensors_pdrv_registered = 1;
4806
4711 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); 4807 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
4808 if (!ret) {
4809 tp_features.platform_drv_attrs_registered = 1;
4810 ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
4811 }
4712 if (ret) { 4812 if (ret) {
4713 printk(IBM_ERR "unable to create sysfs driver attributes\n"); 4813 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4714 thinkpad_acpi_module_exit(); 4814 thinkpad_acpi_module_exit();
4715 return ret; 4815 return ret;
4716 } 4816 }
4717 tp_features.platform_drv_attrs_registered = 1; 4817 tp_features.sensors_pdrv_attrs_registered = 1;
4718 4818
4719 4819
4720 /* Device initialization */ 4820 /* Device initialization */
@@ -4727,7 +4827,26 @@ static int __init thinkpad_acpi_module_init(void)
4727 thinkpad_acpi_module_exit(); 4827 thinkpad_acpi_module_exit();
4728 return ret; 4828 return ret;
4729 } 4829 }
4730 tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev); 4830 tpacpi_sensors_pdev = platform_device_register_simple(
4831 IBM_HWMON_DRVR_NAME,
4832 -1, NULL, 0);
4833 if (IS_ERR(tpacpi_sensors_pdev)) {
4834 ret = PTR_ERR(tpacpi_sensors_pdev);
4835 tpacpi_sensors_pdev = NULL;
4836 printk(IBM_ERR "unable to register hwmon platform device\n");
4837 thinkpad_acpi_module_exit();
4838 return ret;
4839 }
4840 ret = device_create_file(&tpacpi_sensors_pdev->dev,
4841 &dev_attr_thinkpad_acpi_pdev_name);
4842 if (ret) {
4843 printk(IBM_ERR
4844 "unable to create sysfs hwmon device attributes\n");
4845 thinkpad_acpi_module_exit();
4846 return ret;
4847 }
4848 tp_features.sensors_pdev_attrs_registered = 1;
4849 tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev);
4731 if (IS_ERR(tpacpi_hwmon)) { 4850 if (IS_ERR(tpacpi_hwmon)) {
4732 ret = PTR_ERR(tpacpi_hwmon); 4851 ret = PTR_ERR(tpacpi_hwmon);
4733 tpacpi_hwmon = NULL; 4852 tpacpi_hwmon = NULL;
@@ -4735,6 +4854,7 @@ static int __init thinkpad_acpi_module_init(void)
4735 thinkpad_acpi_module_exit(); 4854 thinkpad_acpi_module_exit();
4736 return ret; 4855 return ret;
4737 } 4856 }
4857 mutex_init(&tpacpi_inputdev_send_mutex);
4738 tpacpi_inputdev = input_allocate_device(); 4858 tpacpi_inputdev = input_allocate_device();
4739 if (!tpacpi_inputdev) { 4859 if (!tpacpi_inputdev) {
4740 printk(IBM_ERR "unable to allocate input device\n"); 4860 printk(IBM_ERR "unable to allocate input device\n");
@@ -4769,6 +4889,7 @@ static int __init thinkpad_acpi_module_init(void)
4769 tp_features.input_device_registered = 1; 4889 tp_features.input_device_registered = 1;
4770 } 4890 }
4771 4891
4892 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
4772 return 0; 4893 return 0;
4773} 4894}
4774 4895
@@ -4776,6 +4897,8 @@ static void thinkpad_acpi_module_exit(void)
4776{ 4897{
4777 struct ibm_struct *ibm, *itmp; 4898 struct ibm_struct *ibm, *itmp;
4778 4899
4900 tpacpi_lifecycle = TPACPI_LIFE_EXITING;
4901
4779 list_for_each_entry_safe_reverse(ibm, itmp, 4902 list_for_each_entry_safe_reverse(ibm, itmp,
4780 &tpacpi_all_drivers, 4903 &tpacpi_all_drivers,
4781 all_drivers) { 4904 all_drivers) {
@@ -4794,12 +4917,22 @@ static void thinkpad_acpi_module_exit(void)
4794 if (tpacpi_hwmon) 4917 if (tpacpi_hwmon)
4795 hwmon_device_unregister(tpacpi_hwmon); 4918 hwmon_device_unregister(tpacpi_hwmon);
4796 4919
4920 if (tp_features.sensors_pdev_attrs_registered)
4921 device_remove_file(&tpacpi_sensors_pdev->dev,
4922 &dev_attr_thinkpad_acpi_pdev_name);
4923 if (tpacpi_sensors_pdev)
4924 platform_device_unregister(tpacpi_sensors_pdev);
4797 if (tpacpi_pdev) 4925 if (tpacpi_pdev)
4798 platform_device_unregister(tpacpi_pdev); 4926 platform_device_unregister(tpacpi_pdev);
4799 4927
4928 if (tp_features.sensors_pdrv_attrs_registered)
4929 tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
4800 if (tp_features.platform_drv_attrs_registered) 4930 if (tp_features.platform_drv_attrs_registered)
4801 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); 4931 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
4802 4932
4933 if (tp_features.sensors_pdrv_registered)
4934 platform_driver_unregister(&tpacpi_hwmon_pdriver);
4935
4803 if (tp_features.platform_drv_registered) 4936 if (tp_features.platform_drv_registered)
4804 platform_driver_unregister(&tpacpi_pdriver); 4937 platform_driver_unregister(&tpacpi_pdriver);
4805 4938
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 082a1cbc16c0..c5fdd688cc99 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -58,13 +58,14 @@
58 58
59#define IBM_NAME "thinkpad" 59#define IBM_NAME "thinkpad"
60#define IBM_DESC "ThinkPad ACPI Extras" 60#define IBM_DESC "ThinkPad ACPI Extras"
61#define IBM_FILE "thinkpad_acpi" 61#define IBM_FILE IBM_NAME "_acpi"
62#define IBM_URL "http://ibm-acpi.sf.net/" 62#define IBM_URL "http://ibm-acpi.sf.net/"
63#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net" 63#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net"
64 64
65#define IBM_PROC_DIR "ibm" 65#define IBM_PROC_DIR "ibm"
66#define IBM_ACPI_EVENT_PREFIX "ibm" 66#define IBM_ACPI_EVENT_PREFIX "ibm"
67#define IBM_DRVR_NAME IBM_FILE 67#define IBM_DRVR_NAME IBM_FILE
68#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
68 69
69#define IBM_LOG IBM_FILE ": " 70#define IBM_LOG IBM_FILE ": "
70#define IBM_ERR KERN_ERR IBM_LOG 71#define IBM_ERR KERN_ERR IBM_LOG
@@ -171,6 +172,7 @@ static int parse_strtoul(const char *buf, unsigned long max,
171 172
172/* Device model */ 173/* Device model */
173static struct platform_device *tpacpi_pdev; 174static struct platform_device *tpacpi_pdev;
175static struct platform_device *tpacpi_sensors_pdev;
174static struct class_device *tpacpi_hwmon; 176static struct class_device *tpacpi_hwmon;
175static struct platform_driver tpacpi_pdriver; 177static struct platform_driver tpacpi_pdriver;
176static struct input_dev *tpacpi_inputdev; 178static struct input_dev *tpacpi_inputdev;
@@ -233,22 +235,25 @@ struct ibm_init_struct {
233 235
234static struct { 236static struct {
235#ifdef CONFIG_THINKPAD_ACPI_BAY 237#ifdef CONFIG_THINKPAD_ACPI_BAY
236 u16 bay_status:1; 238 u32 bay_status:1;
237 u16 bay_eject:1; 239 u32 bay_eject:1;
238 u16 bay_status2:1; 240 u32 bay_status2:1;
239 u16 bay_eject2:1; 241 u32 bay_eject2:1;
240#endif 242#endif
241 u16 bluetooth:1; 243 u32 bluetooth:1;
242 u16 hotkey:1; 244 u32 hotkey:1;
243 u16 hotkey_mask:1; 245 u32 hotkey_mask:1;
244 u16 hotkey_wlsw:1; 246 u32 hotkey_wlsw:1;
245 u16 light:1; 247 u32 light:1;
246 u16 light_status:1; 248 u32 light_status:1;
247 u16 wan:1; 249 u32 wan:1;
248 u16 fan_ctrl_status_undef:1; 250 u32 fan_ctrl_status_undef:1;
249 u16 input_device_registered:1; 251 u32 input_device_registered:1;
250 u16 platform_drv_registered:1; 252 u32 platform_drv_registered:1;
251 u16 platform_drv_attrs_registered:1; 253 u32 platform_drv_attrs_registered:1;
254 u32 sensors_pdrv_registered:1;
255 u32 sensors_pdrv_attrs_registered:1;
256 u32 sensors_pdev_attrs_registered:1;
252} tp_features; 257} tp_features;
253 258
254struct thinkpad_id_data { 259struct thinkpad_id_data {