aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/dell-smm-hwmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/dell-smm-hwmon.c')
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c85
1 files changed, 62 insertions, 23 deletions
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index c43318d3416e..2ac87d553e22 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -35,6 +35,7 @@
35#include <linux/uaccess.h> 35#include <linux/uaccess.h>
36#include <linux/io.h> 36#include <linux/io.h>
37#include <linux/sched.h> 37#include <linux/sched.h>
38#include <linux/ctype.h>
38 39
39#include <linux/i8k.h> 40#include <linux/i8k.h>
40 41
@@ -66,11 +67,13 @@
66 67
67static DEFINE_MUTEX(i8k_mutex); 68static DEFINE_MUTEX(i8k_mutex);
68static char bios_version[4]; 69static char bios_version[4];
70static char bios_machineid[16];
69static struct device *i8k_hwmon_dev; 71static struct device *i8k_hwmon_dev;
70static u32 i8k_hwmon_flags; 72static u32 i8k_hwmon_flags;
71static uint i8k_fan_mult = I8K_FAN_MULT; 73static uint i8k_fan_mult = I8K_FAN_MULT;
72static uint i8k_pwm_mult; 74static uint i8k_pwm_mult;
73static uint i8k_fan_max = I8K_FAN_HIGH; 75static uint i8k_fan_max = I8K_FAN_HIGH;
76static bool disallow_fan_type_call;
74 77
75#define I8K_HWMON_HAVE_TEMP1 (1 << 0) 78#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
76#define I8K_HWMON_HAVE_TEMP2 (1 << 1) 79#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
@@ -94,13 +97,13 @@ module_param(ignore_dmi, bool, 0);
94MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); 97MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
95 98
96#if IS_ENABLED(CONFIG_I8K) 99#if IS_ENABLED(CONFIG_I8K)
97static bool restricted; 100static bool restricted = true;
98module_param(restricted, bool, 0); 101module_param(restricted, bool, 0);
99MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); 102MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
100 103
101static bool power_status; 104static bool power_status;
102module_param(power_status, bool, 0600); 105module_param(power_status, bool, 0600);
103MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); 106MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
104#endif 107#endif
105 108
106static uint fan_mult; 109static uint fan_mult;
@@ -235,14 +238,28 @@ static int i8k_get_fan_speed(int fan)
235/* 238/*
236 * Read the fan type. 239 * Read the fan type.
237 */ 240 */
238static int i8k_get_fan_type(int fan) 241static int _i8k_get_fan_type(int fan)
239{ 242{
240 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, }; 243 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
241 244
245 if (disallow_fan_type_call)
246 return -EINVAL;
247
242 regs.ebx = fan & 0xff; 248 regs.ebx = fan & 0xff;
243 return i8k_smm(&regs) ? : regs.eax & 0xff; 249 return i8k_smm(&regs) ? : regs.eax & 0xff;
244} 250}
245 251
252static int i8k_get_fan_type(int fan)
253{
254 /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
255 static int types[2] = { INT_MIN, INT_MIN };
256
257 if (types[fan] == INT_MIN)
258 types[fan] = _i8k_get_fan_type(fan);
259
260 return types[fan];
261}
262
246/* 263/*
247 * Read the fan nominal rpm for specific fan speed. 264 * Read the fan nominal rpm for specific fan speed.
248 */ 265 */
@@ -387,14 +404,20 @@ i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
387 404
388 switch (cmd) { 405 switch (cmd) {
389 case I8K_BIOS_VERSION: 406 case I8K_BIOS_VERSION:
407 if (!isdigit(bios_version[0]) || !isdigit(bios_version[1]) ||
408 !isdigit(bios_version[2]))
409 return -EINVAL;
410
390 val = (bios_version[0] << 16) | 411 val = (bios_version[0] << 16) |
391 (bios_version[1] << 8) | bios_version[2]; 412 (bios_version[1] << 8) | bios_version[2];
392 break; 413 break;
393 414
394 case I8K_MACHINE_ID: 415 case I8K_MACHINE_ID:
395 memset(buff, 0, 16); 416 if (restricted && !capable(CAP_SYS_ADMIN))
396 strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), 417 return -EPERM;
397 sizeof(buff)); 418
419 memset(buff, 0, sizeof(buff));
420 strlcpy(buff, bios_machineid, sizeof(buff));
398 break; 421 break;
399 422
400 case I8K_FN_STATUS: 423 case I8K_FN_STATUS:
@@ -511,7 +534,7 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
511 seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n", 534 seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
512 I8K_PROC_FMT, 535 I8K_PROC_FMT,
513 bios_version, 536 bios_version,
514 i8k_get_dmi_data(DMI_PRODUCT_SERIAL), 537 (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
515 cpu_temp, 538 cpu_temp,
516 left_fan, right_fan, left_speed, right_speed, 539 left_fan, right_fan, left_speed, right_speed,
517 ac_power, fn_key); 540 ac_power, fn_key);
@@ -718,6 +741,9 @@ static struct attribute *i8k_attrs[] = {
718static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, 741static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
719 int index) 742 int index)
720{ 743{
744 if (disallow_fan_type_call &&
745 (index == 9 || index == 12))
746 return 0;
721 if (index >= 0 && index <= 1 && 747 if (index >= 0 && index <= 1 &&
722 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) 748 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
723 return 0; 749 return 0;
@@ -767,13 +793,17 @@ static int __init i8k_init_hwmon(void)
767 if (err >= 0) 793 if (err >= 0)
768 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; 794 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
769 795
770 /* First fan attributes, if fan type is OK */ 796 /* First fan attributes, if fan status or type is OK */
771 err = i8k_get_fan_type(0); 797 err = i8k_get_fan_status(0);
798 if (err < 0)
799 err = i8k_get_fan_type(0);
772 if (err >= 0) 800 if (err >= 0)
773 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; 801 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
774 802
775 /* Second fan attributes, if fan type is OK */ 803 /* Second fan attributes, if fan status or type is OK */
776 err = i8k_get_fan_type(1); 804 err = i8k_get_fan_status(1);
805 if (err < 0)
806 err = i8k_get_fan_type(1);
777 if (err >= 0) 807 if (err >= 0)
778 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; 808 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
779 809
@@ -929,12 +959,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
929 959
930MODULE_DEVICE_TABLE(dmi, i8k_dmi_table); 960MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
931 961
932static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = { 962/*
963 * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
964 * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
965 * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
966 * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
967 */
968static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
933 { 969 {
934 /*
935 * CPU fan speed going up and down on Dell Studio XPS 8000
936 * for unknown reasons.
937 */
938 .ident = "Dell Studio XPS 8000", 970 .ident = "Dell Studio XPS 8000",
939 .matches = { 971 .matches = {
940 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 972 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -942,16 +974,19 @@ static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
942 }, 974 },
943 }, 975 },
944 { 976 {
945 /*
946 * CPU fan speed going up and down on Dell Studio XPS 8100
947 * for unknown reasons.
948 */
949 .ident = "Dell Studio XPS 8100", 977 .ident = "Dell Studio XPS 8100",
950 .matches = { 978 .matches = {
951 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 979 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
952 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"), 980 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
953 }, 981 },
954 }, 982 },
983 {
984 .ident = "Dell Inspiron 580",
985 .matches = {
986 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
987 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
988 },
989 },
955 { } 990 { }
956}; 991};
957 992
@@ -966,8 +1001,7 @@ static int __init i8k_probe(void)
966 /* 1001 /*
967 * Get DMI information 1002 * Get DMI information
968 */ 1003 */
969 if (!dmi_check_system(i8k_dmi_table) || 1004 if (!dmi_check_system(i8k_dmi_table)) {
970 dmi_check_system(i8k_blacklist_dmi_table)) {
971 if (!ignore_dmi && !force) 1005 if (!ignore_dmi && !force)
972 return -ENODEV; 1006 return -ENODEV;
973 1007
@@ -978,8 +1012,13 @@ static int __init i8k_probe(void)
978 i8k_get_dmi_data(DMI_BIOS_VERSION)); 1012 i8k_get_dmi_data(DMI_BIOS_VERSION));
979 } 1013 }
980 1014
1015 if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
1016 disallow_fan_type_call = true;
1017
981 strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), 1018 strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
982 sizeof(bios_version)); 1019 sizeof(bios_version));
1020 strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
1021 sizeof(bios_machineid));
983 1022
984 /* 1023 /*
985 * Get SMM Dell signature 1024 * Get SMM Dell signature