diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2015-05-14 07:16:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-24 15:48:12 -0400 |
commit | 039ae58503f3349157a852c2cd5555a630f0bfaf (patch) | |
tree | f11693717d17ba82c4ae7bcae552aafdcd32076c | |
parent | a5afba16c641dc1dda837cfc32dea1e37666d31a (diff) |
hwmon: Allow to compile dell-smm-hwmon driver without /proc/i8k
This patch splits CONFIG_I8K compile option to SENSORS_DELL_SMM and CONFIG_I8K.
Option SENSORS_DELL_SMM is now used to enable compilation of dell-smm-hwmon
driver and old CONFIG_I8K option to enable /proc/i8k interface in driver.
So this change allows to compile dell-smm-hwmon driver without legacy /proc/i8k
interface which is needed only for old Dell Inspirion models or for userspace
i8kutils package.
For backward compatibility when CONFIG_I8K is enabled then also SENSORS_DELL_SMM
is enabled and so driver dell-smm-hwmon (with /proc/i8k) is compiled.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | arch/x86/Kconfig | 25 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 11 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwmon/dell-smm-hwmon.c | 150 |
4 files changed, 106 insertions, 82 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 226d5696e1d1..7b756b337926 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1055,24 +1055,19 @@ config TOSHIBA | |||
1055 | Say N otherwise. | 1055 | Say N otherwise. |
1056 | 1056 | ||
1057 | config I8K | 1057 | config I8K |
1058 | tristate "Dell laptop support" | 1058 | tristate "Dell i8k legacy laptop support" |
1059 | select HWMON | 1059 | select HWMON |
1060 | select SENSORS_DELL_SMM | ||
1060 | ---help--- | 1061 | ---help--- |
1061 | This adds a driver to safely access the System Management Mode | 1062 | This option enables legacy /proc/i8k userspace interface in hwmon |
1062 | of the CPU on the Dell Inspiron 8000. The System Management Mode | 1063 | dell-smm-hwmon driver. Character file /proc/i8k reports bios version, |
1063 | is used to read cpu temperature and cooling fan status and to | 1064 | temperature and allows controlling fan speeds of Dell laptops via |
1064 | control the fans on the I8K portables. | 1065 | System Management Mode. For old Dell laptops (like Dell Inspiron 8000) |
1066 | it reports also power and hotkey status. For fan speed control is | ||
1067 | needed userspace package i8kutils. | ||
1065 | 1068 | ||
1066 | This driver has been tested only on the Inspiron 8000 but it may | 1069 | Say Y if you intend to run this kernel on old Dell laptops or want to |
1067 | also work with other Dell laptops. You can force loading on other | 1070 | use userspace package i8kutils. |
1068 | models by passing the parameter `force=1' to the module. Use at | ||
1069 | your own risk. | ||
1070 | |||
1071 | For information on utilities to make use of this driver see the | ||
1072 | I8K Linux utilities web site at: | ||
1073 | <http://people.debian.org/~dz/i8k/> | ||
1074 | |||
1075 | Say Y if you intend to run this kernel on a Dell Inspiron 8000. | ||
1076 | Say N otherwise. | 1071 | Say N otherwise. |
1077 | 1072 | ||
1078 | config X86_REBOOTFIXUPS | 1073 | config X86_REBOOTFIXUPS |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 25d9e72627e9..bc9d90b108d2 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -371,6 +371,17 @@ config SENSORS_DS1621 | |||
371 | This driver can also be built as a module. If so, the module | 371 | This driver can also be built as a module. If so, the module |
372 | will be called ds1621. | 372 | will be called ds1621. |
373 | 373 | ||
374 | config SENSORS_DELL_SMM | ||
375 | tristate "Dell laptop SMM BIOS hwmon driver" | ||
376 | depends on X86 | ||
377 | help | ||
378 | This hwmon driver adds support for reporting temperature of different | ||
379 | sensors and controls the fans on Dell laptops via System Management | ||
380 | Mode provided by Dell BIOS. | ||
381 | |||
382 | When option I8K is also enabled this driver provides legacy /proc/i8k | ||
383 | userspace interface for i8kutils package. | ||
384 | |||
374 | config SENSORS_DA9052_ADC | 385 | config SENSORS_DA9052_ADC |
375 | tristate "Dialog DA9052/DA9053 ADC" | 386 | tristate "Dialog DA9052/DA9053 ADC" |
376 | depends on PMIC_DA9052 | 387 | depends on PMIC_DA9052 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 51533acfa01e..6cacd0ff06c3 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | |||
49 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o | 49 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o |
50 | obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o | 50 | obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o |
51 | obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o | 51 | obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o |
52 | obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o | ||
52 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o | 53 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o |
53 | obj-$(CONFIG_SENSORS_DS620) += ds620.o | 54 | obj-$(CONFIG_SENSORS_DS620) += ds620.o |
54 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 55 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
@@ -156,7 +157,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o | |||
156 | obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o | 157 | obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o |
157 | obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o | 158 | obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o |
158 | obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o | 159 | obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o |
159 | obj-$(CONFIG_I8K) += dell-smm-hwmon.o | ||
160 | 160 | ||
161 | obj-$(CONFIG_PMBUS) += pmbus/ | 161 | obj-$(CONFIG_PMBUS) += pmbus/ |
162 | 162 | ||
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 65d314b0f197..2a808822af21 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c | |||
@@ -81,7 +81,7 @@ static uint i8k_fan_max = I8K_FAN_HIGH; | |||
81 | 81 | ||
82 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | 82 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); |
83 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | 83 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); |
84 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); | 84 | MODULE_DESCRIPTION("Dell laptop SMM BIOS hwmon driver"); |
85 | MODULE_LICENSE("GPL"); | 85 | MODULE_LICENSE("GPL"); |
86 | MODULE_ALIAS("i8k"); | 86 | MODULE_ALIAS("i8k"); |
87 | 87 | ||
@@ -93,6 +93,7 @@ static bool ignore_dmi; | |||
93 | module_param(ignore_dmi, bool, 0); | 93 | module_param(ignore_dmi, bool, 0); |
94 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); | 94 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); |
95 | 95 | ||
96 | #if IS_ENABLED(CONFIG_I8K) | ||
96 | static bool restricted; | 97 | static bool restricted; |
97 | module_param(restricted, bool, 0); | 98 | module_param(restricted, bool, 0); |
98 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); | 99 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); |
@@ -100,6 +101,7 @@ MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); | |||
100 | static bool power_status; | 101 | static bool power_status; |
101 | module_param(power_status, bool, 0600); | 102 | module_param(power_status, bool, 0600); |
102 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); | 103 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); |
104 | #endif | ||
103 | 105 | ||
104 | static uint fan_mult; | 106 | static uint fan_mult; |
105 | module_param(fan_mult, uint, 0); | 107 | module_param(fan_mult, uint, 0); |
@@ -109,18 +111,6 @@ static uint fan_max; | |||
109 | module_param(fan_max, uint, 0); | 111 | module_param(fan_max, uint, 0); |
110 | MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)"); | 112 | MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)"); |
111 | 113 | ||
112 | static int i8k_open_fs(struct inode *inode, struct file *file); | ||
113 | static long i8k_ioctl(struct file *, unsigned int, unsigned long); | ||
114 | |||
115 | static const struct file_operations i8k_fops = { | ||
116 | .owner = THIS_MODULE, | ||
117 | .open = i8k_open_fs, | ||
118 | .read = seq_read, | ||
119 | .llseek = seq_lseek, | ||
120 | .release = single_release, | ||
121 | .unlocked_ioctl = i8k_ioctl, | ||
122 | }; | ||
123 | |||
124 | struct smm_regs { | 114 | struct smm_regs { |
125 | unsigned int eax; | 115 | unsigned int eax; |
126 | unsigned int ebx __packed; | 116 | unsigned int ebx __packed; |
@@ -221,45 +211,6 @@ out: | |||
221 | } | 211 | } |
222 | 212 | ||
223 | /* | 213 | /* |
224 | * Read the Fn key status. | ||
225 | */ | ||
226 | static int i8k_get_fn_status(void) | ||
227 | { | ||
228 | struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, }; | ||
229 | int rc; | ||
230 | |||
231 | rc = i8k_smm(®s); | ||
232 | if (rc < 0) | ||
233 | return rc; | ||
234 | |||
235 | switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) { | ||
236 | case I8K_FN_UP: | ||
237 | return I8K_VOL_UP; | ||
238 | case I8K_FN_DOWN: | ||
239 | return I8K_VOL_DOWN; | ||
240 | case I8K_FN_MUTE: | ||
241 | return I8K_VOL_MUTE; | ||
242 | default: | ||
243 | return 0; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Read the power status. | ||
249 | */ | ||
250 | static int i8k_get_power_status(void) | ||
251 | { | ||
252 | struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, }; | ||
253 | int rc; | ||
254 | |||
255 | rc = i8k_smm(®s); | ||
256 | if (rc < 0) | ||
257 | return rc; | ||
258 | |||
259 | return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY; | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * Read the fan status. | 214 | * Read the fan status. |
264 | */ | 215 | */ |
265 | static int i8k_get_fan_status(int fan) | 216 | static int i8k_get_fan_status(int fan) |
@@ -378,6 +329,51 @@ static int i8k_get_dell_signature(int req_fn) | |||
378 | return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; | 329 | return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; |
379 | } | 330 | } |
380 | 331 | ||
332 | #if IS_ENABLED(CONFIG_I8K) | ||
333 | |||
334 | /* | ||
335 | * Read the Fn key status. | ||
336 | */ | ||
337 | static int i8k_get_fn_status(void) | ||
338 | { | ||
339 | struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, }; | ||
340 | int rc; | ||
341 | |||
342 | rc = i8k_smm(®s); | ||
343 | if (rc < 0) | ||
344 | return rc; | ||
345 | |||
346 | switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) { | ||
347 | case I8K_FN_UP: | ||
348 | return I8K_VOL_UP; | ||
349 | case I8K_FN_DOWN: | ||
350 | return I8K_VOL_DOWN; | ||
351 | case I8K_FN_MUTE: | ||
352 | return I8K_VOL_MUTE; | ||
353 | default: | ||
354 | return 0; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * Read the power status. | ||
360 | */ | ||
361 | static int i8k_get_power_status(void) | ||
362 | { | ||
363 | struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, }; | ||
364 | int rc; | ||
365 | |||
366 | rc = i8k_smm(®s); | ||
367 | if (rc < 0) | ||
368 | return rc; | ||
369 | |||
370 | return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY; | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * Procfs interface | ||
375 | */ | ||
376 | |||
381 | static int | 377 | static int |
382 | i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) | 378 | i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) |
383 | { | 379 | { |
@@ -528,6 +524,37 @@ static int i8k_open_fs(struct inode *inode, struct file *file) | |||
528 | return single_open(file, i8k_proc_show, NULL); | 524 | return single_open(file, i8k_proc_show, NULL); |
529 | } | 525 | } |
530 | 526 | ||
527 | static const struct file_operations i8k_fops = { | ||
528 | .owner = THIS_MODULE, | ||
529 | .open = i8k_open_fs, | ||
530 | .read = seq_read, | ||
531 | .llseek = seq_lseek, | ||
532 | .release = single_release, | ||
533 | .unlocked_ioctl = i8k_ioctl, | ||
534 | }; | ||
535 | |||
536 | static void __init i8k_init_procfs(void) | ||
537 | { | ||
538 | /* Register the proc entry */ | ||
539 | proc_create("i8k", 0, NULL, &i8k_fops); | ||
540 | } | ||
541 | |||
542 | static void __exit i8k_exit_procfs(void) | ||
543 | { | ||
544 | remove_proc_entry("i8k", NULL); | ||
545 | } | ||
546 | |||
547 | #else | ||
548 | |||
549 | static inline void __init i8k_init_procfs(void) | ||
550 | { | ||
551 | } | ||
552 | |||
553 | static inline void __exit i8k_exit_procfs(void) | ||
554 | { | ||
555 | } | ||
556 | |||
557 | #endif | ||
531 | 558 | ||
532 | /* | 559 | /* |
533 | * Hwmon interface | 560 | * Hwmon interface |
@@ -750,8 +777,8 @@ static int __init i8k_init_hwmon(void) | |||
750 | if (err >= 0) | 777 | if (err >= 0) |
751 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; | 778 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; |
752 | 779 | ||
753 | i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "i8k", NULL, | 780 | i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "dell-smm", |
754 | i8k_groups); | 781 | NULL, i8k_groups); |
755 | if (IS_ERR(i8k_hwmon_dev)) { | 782 | if (IS_ERR(i8k_hwmon_dev)) { |
756 | err = PTR_ERR(i8k_hwmon_dev); | 783 | err = PTR_ERR(i8k_hwmon_dev); |
757 | i8k_hwmon_dev = NULL; | 784 | i8k_hwmon_dev = NULL; |
@@ -976,33 +1003,24 @@ static int __init i8k_probe(void) | |||
976 | 1003 | ||
977 | static int __init i8k_init(void) | 1004 | static int __init i8k_init(void) |
978 | { | 1005 | { |
979 | struct proc_dir_entry *proc_i8k; | ||
980 | int err; | 1006 | int err; |
981 | 1007 | ||
982 | /* Are we running on an supported laptop? */ | 1008 | /* Are we running on an supported laptop? */ |
983 | if (i8k_probe()) | 1009 | if (i8k_probe()) |
984 | return -ENODEV; | 1010 | return -ENODEV; |
985 | 1011 | ||
986 | /* Register the proc entry */ | ||
987 | proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops); | ||
988 | if (!proc_i8k) | ||
989 | return -ENOENT; | ||
990 | |||
991 | err = i8k_init_hwmon(); | 1012 | err = i8k_init_hwmon(); |
992 | if (err) | 1013 | if (err) |
993 | goto exit_remove_proc; | 1014 | return err; |
994 | 1015 | ||
1016 | i8k_init_procfs(); | ||
995 | return 0; | 1017 | return 0; |
996 | |||
997 | exit_remove_proc: | ||
998 | remove_proc_entry("i8k", NULL); | ||
999 | return err; | ||
1000 | } | 1018 | } |
1001 | 1019 | ||
1002 | static void __exit i8k_exit(void) | 1020 | static void __exit i8k_exit(void) |
1003 | { | 1021 | { |
1004 | hwmon_device_unregister(i8k_hwmon_dev); | 1022 | hwmon_device_unregister(i8k_hwmon_dev); |
1005 | remove_proc_entry("i8k", NULL); | 1023 | i8k_exit_procfs(); |
1006 | } | 1024 | } |
1007 | 1025 | ||
1008 | module_init(i8k_init); | 1026 | module_init(i8k_init); |