Pull hwmon fix from Guenter Roeck: "Improve fan type detection for dell-smm to prevent kernel hang" * tag 'hwmon-for-linus-v4.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: hwmon: (dell-smm) Cache fan_type() calls and change fan detection
Unified · Split
| @@ -238,7 +238,7 @@ static int i8k_get_fan_speed(int fan) · 237 unmodified lines | ||
| 238 | 238 | /* |
| 239 | 239 | * Read the fan type. |
| 240 | 240 | */ |
| 241 | −static int i8k_get_fan_type(int fan) | |
| 241 | +static int _i8k_get_fan_type(int fan) | |
| 242 | 242 | { |
| 243 | 243 | struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, }; |
| 244 | 244 | |
| @@ -249,6 +249,17 @@ static int i8k_get_fan_type(int fan) · 4 unmodified lines | ||
| 249 | 249 | return i8k_smm(®s) ? : regs.eax & 0xff; |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | +static 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 | + | |
| 252 | 263 | /* |
| 253 | 264 | * Read the fan nominal rpm for specific fan speed. |
| 254 | 265 | */ |
| @@ -782,13 +793,17 @@ static int __init i8k_init_hwmon(void) · 527 unmodified lines | ||
| 782 | 793 | if (err >= 0) |
| 783 | 794 | i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; |
| 784 | 795 | |
| 785 | − /* First fan attributes, if fan type is OK */ | |
| 786 | − err = i8k_get_fan_type(0); | |
| 796 | + /* First fan attributes, if fan status or type is OK */ | |
| 797 | + err = i8k_get_fan_status(0); | |
| 798 | + if (err < 0) | |
| 799 | + err = i8k_get_fan_type(0); | |
| 787 | 800 | if (err >= 0) |
| 788 | 801 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; |
| 789 | 802 | |
| 790 | − /* Second fan attributes, if fan type is OK */ | |
| 791 | − err = i8k_get_fan_type(1); | |
| 803 | + /* Second fan attributes, if fan status or type is OK */ | |
| 804 | + err = i8k_get_fan_status(1); | |
| 805 | + if (err < 0) | |
| 806 | + err = i8k_get_fan_type(1); | |
| 792 | 807 | if (err >= 0) |
| 793 | 808 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; |
| 794 | 809 | |