diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 114 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 5 |
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 | */ | ||
755 | static int hotkey_get(int *status, int *mask) | 759 | static 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 | */ | ||
767 | static int hotkey_set(int status, int mask) | 774 | static 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; | 863 | errexit: |
864 | mutex_unlock(&hotkey_mutex); | ||
865 | return res; | ||
849 | } | 866 | } |
850 | 867 | ||
851 | static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = { | 868 | static 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 | ||
2765 | static int fan_set_level(int level) | 2783 | static 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 | ||
2836 | static int fan_set_disable(void) | 2878 | static 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 | ||
2858 | static int fan_set_speed(int speed) | 2909 | static 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 | ||
2876 | static int fan_read(char *p) | 2936 | static 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; | |||
375 | static u8 fan_control_initial_status; | 376 | static u8 fan_control_initial_status; |
376 | static int fan_watchdog_maxinterval; | 377 | static int fan_watchdog_maxinterval; |
377 | 378 | ||
379 | struct mutex fan_mutex; | ||
380 | |||
378 | static acpi_handle fans_handle, gfan_handle, sfan_handle; | 381 | static acpi_handle fans_handle, gfan_handle, sfan_handle; |
379 | 382 | ||
380 | static int fan_init(struct ibm_init_struct *iibm); | 383 | static int fan_init(struct ibm_init_struct *iibm); |
@@ -403,6 +406,8 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc); | |||
403 | static int hotkey_orig_status; | 406 | static int hotkey_orig_status; |
404 | static int hotkey_orig_mask; | 407 | static int hotkey_orig_mask; |
405 | 408 | ||
409 | static struct mutex hotkey_mutex; | ||
410 | |||
406 | static int hotkey_init(struct ibm_init_struct *iibm); | 411 | static int hotkey_init(struct ibm_init_struct *iibm); |
407 | static void hotkey_exit(void); | 412 | static void hotkey_exit(void); |
408 | static int hotkey_get(int *status, int *mask); | 413 | static int hotkey_get(int *status, int *mask); |