aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2015-05-14 07:16:37 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-24 15:48:12 -0400
commit039ae58503f3349157a852c2cd5555a630f0bfaf (patch)
treef11693717d17ba82c4ae7bcae552aafdcd32076c
parenta5afba16c641dc1dda837cfc32dea1e37666d31a (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/Kconfig25
-rw-r--r--drivers/hwmon/Kconfig11
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c150
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
1057config I8K 1057config 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
1078config X86_REBOOTFIXUPS 1073config 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
374config 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
374config SENSORS_DA9052_ADC 385config 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
49obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o 49obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
50obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o 50obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
51obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o 51obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
52obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o
52obj-$(CONFIG_SENSORS_DME1737) += dme1737.o 53obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
53obj-$(CONFIG_SENSORS_DS620) += ds620.o 54obj-$(CONFIG_SENSORS_DS620) += ds620.o
54obj-$(CONFIG_SENSORS_DS1621) += ds1621.o 55obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
@@ -156,7 +157,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
156obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o 157obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
157obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o 158obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
158obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o 159obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
159obj-$(CONFIG_I8K) += dell-smm-hwmon.o
160 160
161obj-$(CONFIG_PMBUS) += pmbus/ 161obj-$(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
82MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); 82MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
83MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); 83MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
84MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); 84MODULE_DESCRIPTION("Dell laptop SMM BIOS hwmon driver");
85MODULE_LICENSE("GPL"); 85MODULE_LICENSE("GPL");
86MODULE_ALIAS("i8k"); 86MODULE_ALIAS("i8k");
87 87
@@ -93,6 +93,7 @@ static bool ignore_dmi;
93module_param(ignore_dmi, bool, 0); 93module_param(ignore_dmi, bool, 0);
94MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); 94MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
95 95
96#if IS_ENABLED(CONFIG_I8K)
96static bool restricted; 97static bool restricted;
97module_param(restricted, bool, 0); 98module_param(restricted, bool, 0);
98MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); 99MODULE_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");
100static bool power_status; 101static bool power_status;
101module_param(power_status, bool, 0600); 102module_param(power_status, bool, 0600);
102MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); 103MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
104#endif
103 105
104static uint fan_mult; 106static uint fan_mult;
105module_param(fan_mult, uint, 0); 107module_param(fan_mult, uint, 0);
@@ -109,18 +111,6 @@ static uint fan_max;
109module_param(fan_max, uint, 0); 111module_param(fan_max, uint, 0);
110MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)"); 112MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
111 113
112static int i8k_open_fs(struct inode *inode, struct file *file);
113static long i8k_ioctl(struct file *, unsigned int, unsigned long);
114
115static 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
124struct smm_regs { 114struct 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 */
226static 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(&regs);
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 */
250static 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(&regs);
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 */
265static int i8k_get_fan_status(int fan) 216static 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 */
337static 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(&regs);
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 */
361static 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(&regs);
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
381static int 377static int
382i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) 378i8k_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
527static 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
536static void __init i8k_init_procfs(void)
537{
538 /* Register the proc entry */
539 proc_create("i8k", 0, NULL, &i8k_fops);
540}
541
542static void __exit i8k_exit_procfs(void)
543{
544 remove_proc_entry("i8k", NULL);
545}
546
547#else
548
549static inline void __init i8k_init_procfs(void)
550{
551}
552
553static 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
977static int __init i8k_init(void) 1004static 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
1002static void __exit i8k_exit(void) 1020static 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
1008module_init(i8k_init); 1026module_init(i8k_init);