Commit 039ae585 authored by Pali Rohár's avatar Pali Rohár Committed by Greg Kroah-Hartman

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: default avatarPali Rohár <pali.rohar@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a5afba16
...@@ -1055,24 +1055,19 @@ config TOSHIBA ...@@ -1055,24 +1055,19 @@ config TOSHIBA
Say N otherwise. Say N otherwise.
config I8K config I8K
tristate "Dell laptop support" tristate "Dell i8k legacy laptop support"
select HWMON select HWMON
select SENSORS_DELL_SMM
---help--- ---help---
This adds a driver to safely access the System Management Mode This option enables legacy /proc/i8k userspace interface in hwmon
of the CPU on the Dell Inspiron 8000. The System Management Mode dell-smm-hwmon driver. Character file /proc/i8k reports bios version,
is used to read cpu temperature and cooling fan status and to temperature and allows controlling fan speeds of Dell laptops via
control the fans on the I8K portables. System Management Mode. For old Dell laptops (like Dell Inspiron 8000)
it reports also power and hotkey status. For fan speed control is
needed userspace package i8kutils.
This driver has been tested only on the Inspiron 8000 but it may Say Y if you intend to run this kernel on old Dell laptops or want to
also work with other Dell laptops. You can force loading on other use userspace package i8kutils.
models by passing the parameter `force=1' to the module. Use at
your own risk.
For information on utilities to make use of this driver see the
I8K Linux utilities web site at:
<http://people.debian.org/~dz/i8k/>
Say Y if you intend to run this kernel on a Dell Inspiron 8000.
Say N otherwise. Say N otherwise.
config X86_REBOOTFIXUPS config X86_REBOOTFIXUPS
......
...@@ -371,6 +371,17 @@ config SENSORS_DS1621 ...@@ -371,6 +371,17 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called ds1621. will be called ds1621.
config SENSORS_DELL_SMM
tristate "Dell laptop SMM BIOS hwmon driver"
depends on X86
help
This hwmon driver adds support for reporting temperature of different
sensors and controls the fans on Dell laptops via System Management
Mode provided by Dell BIOS.
When option I8K is also enabled this driver provides legacy /proc/i8k
userspace interface for i8kutils package.
config SENSORS_DA9052_ADC config SENSORS_DA9052_ADC
tristate "Dialog DA9052/DA9053 ADC" tristate "Dialog DA9052/DA9053 ADC"
depends on PMIC_DA9052 depends on PMIC_DA9052
......
...@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o ...@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
obj-$(CONFIG_SENSORS_DS620) += ds620.o obj-$(CONFIG_SENSORS_DS620) += ds620.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
...@@ -156,7 +157,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o ...@@ -156,7 +157,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_I8K) += dell-smm-hwmon.o
obj-$(CONFIG_PMBUS) += pmbus/ obj-$(CONFIG_PMBUS) += pmbus/
......
...@@ -81,7 +81,7 @@ static uint i8k_fan_max = I8K_FAN_HIGH; ...@@ -81,7 +81,7 @@ static uint i8k_fan_max = I8K_FAN_HIGH;
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); MODULE_DESCRIPTION("Dell laptop SMM BIOS hwmon driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("i8k"); MODULE_ALIAS("i8k");
...@@ -93,6 +93,7 @@ static bool ignore_dmi; ...@@ -93,6 +93,7 @@ static bool ignore_dmi;
module_param(ignore_dmi, bool, 0); module_param(ignore_dmi, bool, 0);
MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
#if IS_ENABLED(CONFIG_I8K)
static bool restricted; static bool restricted;
module_param(restricted, bool, 0); module_param(restricted, bool, 0);
MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); 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,6 +101,7 @@ MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
static bool power_status; static bool power_status;
module_param(power_status, bool, 0600); module_param(power_status, bool, 0600);
MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
#endif
static uint fan_mult; static uint fan_mult;
module_param(fan_mult, uint, 0); module_param(fan_mult, uint, 0);
...@@ -109,18 +111,6 @@ static uint fan_max; ...@@ -109,18 +111,6 @@ static uint fan_max;
module_param(fan_max, uint, 0); module_param(fan_max, uint, 0);
MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)"); MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
static int i8k_open_fs(struct inode *inode, struct file *file);
static long i8k_ioctl(struct file *, unsigned int, unsigned long);
static const struct file_operations i8k_fops = {
.owner = THIS_MODULE,
.open = i8k_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.unlocked_ioctl = i8k_ioctl,
};
struct smm_regs { struct smm_regs {
unsigned int eax; unsigned int eax;
unsigned int ebx __packed; unsigned int ebx __packed;
...@@ -220,45 +210,6 @@ static int i8k_smm(struct smm_regs *regs) ...@@ -220,45 +210,6 @@ static int i8k_smm(struct smm_regs *regs)
return rc; return rc;
} }
/*
* Read the Fn key status.
*/
static int i8k_get_fn_status(void)
{
struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
int rc;
rc = i8k_smm(&regs);
if (rc < 0)
return rc;
switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
case I8K_FN_UP:
return I8K_VOL_UP;
case I8K_FN_DOWN:
return I8K_VOL_DOWN;
case I8K_FN_MUTE:
return I8K_VOL_MUTE;
default:
return 0;
}
}
/*
* Read the power status.
*/
static int i8k_get_power_status(void)
{
struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
int rc;
rc = i8k_smm(&regs);
if (rc < 0)
return rc;
return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
}
/* /*
* Read the fan status. * Read the fan status.
*/ */
...@@ -378,6 +329,51 @@ static int i8k_get_dell_signature(int req_fn) ...@@ -378,6 +329,51 @@ static int i8k_get_dell_signature(int req_fn)
return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
} }
#if IS_ENABLED(CONFIG_I8K)
/*
* Read the Fn key status.
*/
static int i8k_get_fn_status(void)
{
struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
int rc;
rc = i8k_smm(&regs);
if (rc < 0)
return rc;
switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
case I8K_FN_UP:
return I8K_VOL_UP;
case I8K_FN_DOWN:
return I8K_VOL_DOWN;
case I8K_FN_MUTE:
return I8K_VOL_MUTE;
default:
return 0;
}
}
/*
* Read the power status.
*/
static int i8k_get_power_status(void)
{
struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
int rc;
rc = i8k_smm(&regs);
if (rc < 0)
return rc;
return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
}
/*
* Procfs interface
*/
static int static int
i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
{ {
...@@ -528,6 +524,37 @@ static int i8k_open_fs(struct inode *inode, struct file *file) ...@@ -528,6 +524,37 @@ static int i8k_open_fs(struct inode *inode, struct file *file)
return single_open(file, i8k_proc_show, NULL); return single_open(file, i8k_proc_show, NULL);
} }
static const struct file_operations i8k_fops = {
.owner = THIS_MODULE,
.open = i8k_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.unlocked_ioctl = i8k_ioctl,
};
static void __init i8k_init_procfs(void)
{
/* Register the proc entry */
proc_create("i8k", 0, NULL, &i8k_fops);
}
static void __exit i8k_exit_procfs(void)
{
remove_proc_entry("i8k", NULL);
}
#else
static inline void __init i8k_init_procfs(void)
{
}
static inline void __exit i8k_exit_procfs(void)
{
}
#endif
/* /*
* Hwmon interface * Hwmon interface
...@@ -750,8 +777,8 @@ static int __init i8k_init_hwmon(void) ...@@ -750,8 +777,8 @@ static int __init i8k_init_hwmon(void)
if (err >= 0) if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "i8k", NULL, i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "dell-smm",
i8k_groups); NULL, i8k_groups);
if (IS_ERR(i8k_hwmon_dev)) { if (IS_ERR(i8k_hwmon_dev)) {
err = PTR_ERR(i8k_hwmon_dev); err = PTR_ERR(i8k_hwmon_dev);
i8k_hwmon_dev = NULL; i8k_hwmon_dev = NULL;
...@@ -976,33 +1003,24 @@ static int __init i8k_probe(void) ...@@ -976,33 +1003,24 @@ static int __init i8k_probe(void)
static int __init i8k_init(void) static int __init i8k_init(void)
{ {
struct proc_dir_entry *proc_i8k;
int err; int err;
/* Are we running on an supported laptop? */ /* Are we running on an supported laptop? */
if (i8k_probe()) if (i8k_probe())
return -ENODEV; return -ENODEV;
/* Register the proc entry */
proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops);
if (!proc_i8k)
return -ENOENT;
err = i8k_init_hwmon(); err = i8k_init_hwmon();
if (err) if (err)
goto exit_remove_proc; return err;
i8k_init_procfs();
return 0; return 0;
exit_remove_proc:
remove_proc_entry("i8k", NULL);
return err;
} }
static void __exit i8k_exit(void) static void __exit i8k_exit(void)
{ {
hwmon_device_unregister(i8k_hwmon_dev); hwmon_device_unregister(i8k_hwmon_dev);
remove_proc_entry("i8k", NULL); i8k_exit_procfs();
} }
module_init(i8k_init); module_init(i8k_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment