aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2007-04-24 10:48:15 -0400
committerLen Brown <len.brown@intel.com>2007-04-25 02:00:27 -0400
commit40ca9fdf8aa7d929e2b8939be1e6380d107381e1 (patch)
tree285d9e5a577b87064ecb06ee7aea46e206d1a3ac /drivers/misc
parent7252374a39d794879f5e47bcfa0a16e7599b27b5 (diff)
ACPI: thinkpad-acpi: protect fan and hotkey data structures
Add proper mutex locking to some data structures access subject to races due to concurrent access of driver functions on the hotkey and fan subdrivers. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/thinkpad_acpi.c114
-rw-r--r--drivers/misc/thinkpad_acpi.h5
2 files changed, 92 insertions, 27 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index ca6d15cdc5f0..aa69ff0c1c91 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -704,6 +704,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
704 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 704 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
705 705
706 IBM_ACPIHANDLE_INIT(hkey); 706 IBM_ACPIHANDLE_INIT(hkey);
707 mutex_init(&hotkey_mutex);
707 708
708 /* hotkey not supported on 570 */ 709 /* hotkey not supported on 570 */
709 tp_features.hotkey = hkey_handle != NULL; 710 tp_features.hotkey = hkey_handle != NULL;
@@ -752,6 +753,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
752 } 753 }
753} 754}
754 755
756/*
757 * Call with hotkey_mutex held
758 */
755static int hotkey_get(int *status, int *mask) 759static int hotkey_get(int *status, int *mask)
756{ 760{
757 if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) 761 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
@@ -764,6 +768,9 @@ static int hotkey_get(int *status, int *mask)
764 return 0; 768 return 0;
765} 769}
766 770
771/*
772 * Call with hotkey_mutex held
773 */
767static int hotkey_set(int status, int mask) 774static int hotkey_set(int status, int mask)
768{ 775{
769 int i; 776 int i;
@@ -792,7 +799,11 @@ static int hotkey_read(char *p)
792 return len; 799 return len;
793 } 800 }
794 801
802 res = mutex_lock_interruptible(&hotkey_mutex);
803 if (res < 0)
804 return res;
795 res = hotkey_get(&status, &mask); 805 res = hotkey_get(&status, &mask);
806 mutex_unlock(&hotkey_mutex);
796 if (res) 807 if (res)
797 return res; 808 return res;
798 809
@@ -818,10 +829,15 @@ static int hotkey_write(char *buf)
818 if (!tp_features.hotkey) 829 if (!tp_features.hotkey)
819 return -ENODEV; 830 return -ENODEV;
820 831
832 res = mutex_lock_interruptible(&hotkey_mutex);
833 if (res < 0)
834 return res;
835
821 res = hotkey_get(&status, &mask); 836 res = hotkey_get(&status, &mask);
822 if (res) 837 if (res)
823 return res; 838 goto errexit;
824 839
840 res = 0;
825 while ((cmd = next_cmd(&buf))) { 841 while ((cmd = next_cmd(&buf))) {
826 if (strlencmp(cmd, "enable") == 0) { 842 if (strlencmp(cmd, "enable") == 0) {
827 status = 1; 843 status = 1;
@@ -834,18 +850,19 @@ static int hotkey_write(char *buf)
834 /* mask set */ 850 /* mask set */
835 } else if (sscanf(cmd, "%x", &mask) == 1) { 851 } else if (sscanf(cmd, "%x", &mask) == 1) {
836 /* mask set */ 852 /* mask set */
837 } else 853 } else {
838 return -EINVAL; 854 res = -EINVAL;
855 goto errexit;
856 }
839 do_cmd = 1; 857 do_cmd = 1;
840 } 858 }
841 859
842 if (do_cmd) { 860 if (do_cmd)
843 res = hotkey_set(status, mask); 861 res = hotkey_set(status, mask);
844 if (res)
845 return res;
846 }
847 862
848 return 0; 863errexit:
864 mutex_unlock(&hotkey_mutex);
865 return res;
849} 866}
850 867
851static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = { 868static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
@@ -2575,6 +2592,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
2575{ 2592{
2576 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); 2593 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
2577 2594
2595 mutex_init(&fan_mutex);
2578 fan_status_access_mode = TPACPI_FAN_NONE; 2596 fan_status_access_mode = TPACPI_FAN_NONE;
2579 fan_control_access_mode = TPACPI_FAN_WR_NONE; 2597 fan_control_access_mode = TPACPI_FAN_WR_NONE;
2580 fan_control_commands = 0; 2598 fan_control_commands = 0;
@@ -2764,10 +2782,17 @@ static void fan_watchdog_reset(void)
2764 2782
2765static int fan_set_level(int level) 2783static int fan_set_level(int level)
2766{ 2784{
2785 int res;
2786
2767 switch (fan_control_access_mode) { 2787 switch (fan_control_access_mode) {
2768 case TPACPI_FAN_WR_ACPI_SFAN: 2788 case TPACPI_FAN_WR_ACPI_SFAN:
2769 if (level >= 0 && level <= 7) { 2789 if (level >= 0 && level <= 7) {
2770 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level)) 2790 res = mutex_lock_interruptible(&fan_mutex);
2791 if (res < 0)
2792 return res;
2793 res = acpi_evalf(sfan_handle, NULL, NULL, "vd", level);
2794 mutex_unlock(&fan_mutex);
2795 if (!res)
2771 return -EIO; 2796 return -EIO;
2772 } else 2797 } else
2773 return -EINVAL; 2798 return -EINVAL;
@@ -2780,7 +2805,12 @@ static int fan_set_level(int level)
2780 ((level < 0) || (level > 7))) 2805 ((level < 0) || (level > 7)))
2781 return -EINVAL; 2806 return -EINVAL;
2782 2807
2783 if (!acpi_ec_write(fan_status_offset, level)) 2808 res = mutex_lock_interruptible(&fan_mutex);
2809 if (res < 0)
2810 return res;
2811 res = acpi_ec_write(fan_status_offset, level);
2812 mutex_unlock(&fan_mutex);
2813 if (!res)
2784 return -EIO; 2814 return -EIO;
2785 else 2815 else
2786 tp_features.fan_ctrl_status_undef = 0; 2816 tp_features.fan_ctrl_status_undef = 0;
@@ -2797,25 +2827,33 @@ static int fan_set_enable(void)
2797 u8 s; 2827 u8 s;
2798 int rc; 2828 int rc;
2799 2829
2830 rc = mutex_lock_interruptible(&fan_mutex);
2831 if (rc < 0)
2832 return rc;
2833
2800 switch (fan_control_access_mode) { 2834 switch (fan_control_access_mode) {
2801 case TPACPI_FAN_WR_ACPI_FANS: 2835 case TPACPI_FAN_WR_ACPI_FANS:
2802 case TPACPI_FAN_WR_TPEC: 2836 case TPACPI_FAN_WR_TPEC:
2803 if ((rc = fan_get_status(&s)) < 0) 2837 rc = fan_get_status(&s);
2804 return rc; 2838 if (rc < 0)
2839 break;
2805 2840
2806 /* Don't go out of emergency fan mode */ 2841 /* Don't go out of emergency fan mode */
2807 if (s != 7) 2842 if (s != 7)
2808 s = TP_EC_FAN_AUTO; 2843 s = TP_EC_FAN_AUTO;
2809 2844
2810 if (!acpi_ec_write(fan_status_offset, s)) 2845 if (!acpi_ec_write(fan_status_offset, s))
2811 return -EIO; 2846 rc = -EIO;
2812 else 2847 else {
2813 tp_features.fan_ctrl_status_undef = 0; 2848 tp_features.fan_ctrl_status_undef = 0;
2849 rc = 0;
2850 }
2814 break; 2851 break;
2815 2852
2816 case TPACPI_FAN_WR_ACPI_SFAN: 2853 case TPACPI_FAN_WR_ACPI_SFAN:
2817 if ((rc = fan_get_status(&s)) < 0) 2854 rc = fan_get_status(&s);
2818 return rc; 2855 if (rc < 0)
2856 break;
2819 2857
2820 s &= 0x07; 2858 s &= 0x07;
2821 2859
@@ -2824,53 +2862,75 @@ static int fan_set_enable(void)
2824 s = 4; 2862 s = 4;
2825 2863
2826 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s)) 2864 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
2827 return -EIO; 2865 rc= -EIO;
2866 else
2867 rc = 0;
2828 break; 2868 break;
2829 2869
2830 default: 2870 default:
2831 return -ENXIO; 2871 rc = -ENXIO;
2832 } 2872 }
2833 return 0; 2873
2874 mutex_unlock(&fan_mutex);
2875 return rc;
2834} 2876}
2835 2877
2836static int fan_set_disable(void) 2878static int fan_set_disable(void)
2837{ 2879{
2880 int rc;
2881
2882 rc = mutex_lock_interruptible(&fan_mutex);
2883 if (rc < 0)
2884 return rc;
2885
2886 rc = 0;
2838 switch (fan_control_access_mode) { 2887 switch (fan_control_access_mode) {
2839 case TPACPI_FAN_WR_ACPI_FANS: 2888 case TPACPI_FAN_WR_ACPI_FANS:
2840 case TPACPI_FAN_WR_TPEC: 2889 case TPACPI_FAN_WR_TPEC:
2841 if (!acpi_ec_write(fan_status_offset, 0x00)) 2890 if (!acpi_ec_write(fan_status_offset, 0x00))
2842 return -EIO; 2891 rc = -EIO;
2843 else 2892 else
2844 tp_features.fan_ctrl_status_undef = 0; 2893 tp_features.fan_ctrl_status_undef = 0;
2845 break; 2894 break;
2846 2895
2847 case TPACPI_FAN_WR_ACPI_SFAN: 2896 case TPACPI_FAN_WR_ACPI_SFAN:
2848 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00)) 2897 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
2849 return -EIO; 2898 rc = -EIO;
2850 break; 2899 break;
2851 2900
2852 default: 2901 default:
2853 return -ENXIO; 2902 rc = -ENXIO;
2854 } 2903 }
2855 return 0; 2904
2905 mutex_unlock(&fan_mutex);
2906 return rc;
2856} 2907}
2857 2908
2858static int fan_set_speed(int speed) 2909static int fan_set_speed(int speed)
2859{ 2910{
2911 int rc;
2912
2913 rc = mutex_lock_interruptible(&fan_mutex);
2914 if (rc < 0)
2915 return rc;
2916
2917 rc = 0;
2860 switch (fan_control_access_mode) { 2918 switch (fan_control_access_mode) {
2861 case TPACPI_FAN_WR_ACPI_FANS: 2919 case TPACPI_FAN_WR_ACPI_FANS:
2862 if (speed >= 0 && speed <= 65535) { 2920 if (speed >= 0 && speed <= 65535) {
2863 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd", 2921 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
2864 speed, speed, speed)) 2922 speed, speed, speed))
2865 return -EIO; 2923 rc = -EIO;
2866 } else 2924 } else
2867 return -EINVAL; 2925 rc = -EINVAL;
2868 break; 2926 break;
2869 2927
2870 default: 2928 default:
2871 return -ENXIO; 2929 rc = -ENXIO;
2872 } 2930 }
2873 return 0; 2931
2932 mutex_unlock(&fan_mutex);
2933 return rc;
2874} 2934}
2875 2935
2876static int fan_read(char *p) 2936static int fan_read(char *p)
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 84fdefe0d200..a9feb53c6d3c 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -30,6 +30,7 @@
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/list.h> 32#include <linux/list.h>
33#include <linux/mutex.h>
33 34
34#include <linux/proc_fs.h> 35#include <linux/proc_fs.h>
35#include <linux/sysfs.h> 36#include <linux/sysfs.h>
@@ -375,6 +376,8 @@ static enum fan_control_commands fan_control_commands;
375static u8 fan_control_initial_status; 376static u8 fan_control_initial_status;
376static int fan_watchdog_maxinterval; 377static int fan_watchdog_maxinterval;
377 378
379struct mutex fan_mutex;
380
378static acpi_handle fans_handle, gfan_handle, sfan_handle; 381static acpi_handle fans_handle, gfan_handle, sfan_handle;
379 382
380static int fan_init(struct ibm_init_struct *iibm); 383static int fan_init(struct ibm_init_struct *iibm);
@@ -403,6 +406,8 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc);
403static int hotkey_orig_status; 406static int hotkey_orig_status;
404static int hotkey_orig_mask; 407static int hotkey_orig_mask;
405 408
409static struct mutex hotkey_mutex;
410
406static int hotkey_init(struct ibm_init_struct *iibm); 411static int hotkey_init(struct ibm_init_struct *iibm);
407static void hotkey_exit(void); 412static void hotkey_exit(void);
408static int hotkey_get(int *status, int *mask); 413static int hotkey_get(int *status, int *mask);