aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r--drivers/misc/thinkpad_acpi.c114
1 files changed, 87 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)