hwmon: (dell-smm) Add support for automatic fan mode
Many machines treat fan state 3 as some sort of automatic mode, which is superior to the separate SMM calls for switching to automatic fan mode for two reasons: - the fan control mode can be controlled for each fan separately - the current fan control mode can be retrieved from the BIOS On some machines however, this special fan state does not exist. Fan state 3 acts like a regular fan state on such machines or does not exist at all. Such machines usually use separate SMM calls for enabling/disabling automatic fan control. Add support for it. If the machine supports separate SMM calls for changing the fan control mode, then the other interface is ignored. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20250917181036.10972-4-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net>pull/1354/merge
parent
205c730262
commit
1c1658058c
|
|
@ -38,7 +38,7 @@ fan[1-4]_min RO Minimal Fan speed in RPM
|
||||||
fan[1-4]_max RO Maximal Fan speed in RPM
|
fan[1-4]_max RO Maximal Fan speed in RPM
|
||||||
fan[1-4]_target RO Expected Fan speed in RPM
|
fan[1-4]_target RO Expected Fan speed in RPM
|
||||||
pwm[1-4] RW Control the fan PWM duty-cycle.
|
pwm[1-4] RW Control the fan PWM duty-cycle.
|
||||||
pwm1_enable WO Enable or disable automatic BIOS fan
|
pwm[1-4]_enable RW/WO Enable or disable automatic BIOS fan
|
||||||
control (not supported on all laptops,
|
control (not supported on all laptops,
|
||||||
see below for details).
|
see below for details).
|
||||||
temp[1-10]_input RO Temperature reading in milli-degrees
|
temp[1-10]_input RO Temperature reading in milli-degrees
|
||||||
|
|
@ -49,26 +49,40 @@ temp[1-10]_label RO Temperature sensor label.
|
||||||
Due to the nature of the SMM interface, each pwmX attribute controls
|
Due to the nature of the SMM interface, each pwmX attribute controls
|
||||||
fan number X.
|
fan number X.
|
||||||
|
|
||||||
Disabling automatic BIOS fan control
|
Enabling/Disabling automatic BIOS fan control
|
||||||
------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
On some laptops the BIOS automatically sets fan speed every few
|
There exist two methods for enabling/disabling automatic BIOS fan control:
|
||||||
seconds. Therefore the fan speed set by mean of this driver is quickly
|
|
||||||
overwritten.
|
|
||||||
|
|
||||||
There is experimental support for disabling automatic BIOS fan
|
1. Separate SMM commands to enable/disable automatic BIOS fan control for all fans.
|
||||||
control, at least on laptops where the corresponding SMM command is
|
|
||||||
known, by writing the value ``1`` in the attribute ``pwm1_enable``
|
|
||||||
(writing ``2`` enables automatic BIOS control again). Even if you have
|
|
||||||
more than one fan, all of them are set to either enabled or disabled
|
|
||||||
automatic fan control at the same time and, notwithstanding the name,
|
|
||||||
``pwm1_enable`` sets automatic control for all fans.
|
|
||||||
|
|
||||||
If ``pwm1_enable`` is not available, then it means that SMM codes for
|
2. A special fan state that enables automatic BIOS fan control for a individual fan.
|
||||||
enabling and disabling automatic BIOS fan control are not whitelisted
|
|
||||||
for your hardware. It is possible that codes that work for other
|
The driver cannot reliably detect what method should be used on a given
|
||||||
laptops actually work for yours as well, or that you have to discover
|
device, so instead the following heuristic is used:
|
||||||
new codes.
|
|
||||||
|
- use fan state 3 for enabling BIOS fan control if the maximum fan state
|
||||||
|
setable by the user is smaller than 3 (default setting).
|
||||||
|
|
||||||
|
- use separate SMM commands if device is whitelisted to support them.
|
||||||
|
|
||||||
|
When using the first method, each fan will have a standard ``pwmX_enable``
|
||||||
|
sysfs attribute. Writing ``1`` into this attribute will disable automatic
|
||||||
|
BIOS fan control for the associated fan and set it to maximum speed. Enabling
|
||||||
|
BIOS fan control again can be achieved by writing ``2`` into this attribute.
|
||||||
|
Reading this sysfs attributes returns the current setting as reported by
|
||||||
|
the underlying hardware.
|
||||||
|
|
||||||
|
When using the second method however, only the ``pwm1_enable`` sysfs attribute
|
||||||
|
will be available to enable/disable automatic BIOS fan control globaly for all
|
||||||
|
fans available on a given device. Additionally, this sysfs attribute is write-only
|
||||||
|
as there exists no SMM command for reading the current fan control setting.
|
||||||
|
|
||||||
|
If no ``pwmX_enable`` attributes are available, then it means that the driver
|
||||||
|
cannot use the first method and the SMM codes for enabling and disabling automatic
|
||||||
|
BIOS fan control are not whitelisted for your device. It is possible that codes
|
||||||
|
that work for other laptops actually work for yours as well, or that you have to
|
||||||
|
discover new codes.
|
||||||
|
|
||||||
Check the list ``i8k_whitelist_fan_control`` in file
|
Check the list ``i8k_whitelist_fan_control`` in file
|
||||||
``drivers/hwmon/dell-smm-hwmon.c`` in the kernel tree: as a first
|
``drivers/hwmon/dell-smm-hwmon.c`` in the kernel tree: as a first
|
||||||
|
|
|
||||||
|
|
@ -764,6 +764,13 @@ static int dell_smm_get_cur_state(struct thermal_cooling_device *dev, unsigned l
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A fan state bigger than i8k_fan_max might indicate that
|
||||||
|
* the fan is currently in automatic mode.
|
||||||
|
*/
|
||||||
|
if (ret > cdata->data->i8k_fan_max)
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
*state = ret;
|
*state = ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -851,7 +858,14 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case hwmon_pwm_enable:
|
case hwmon_pwm_enable:
|
||||||
if (auto_fan)
|
if (auto_fan) {
|
||||||
|
/*
|
||||||
|
* The setting affects all fans, so only create a
|
||||||
|
* single attribute.
|
||||||
|
*/
|
||||||
|
if (channel != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is no command for retrieve the current status
|
* There is no command for retrieve the current status
|
||||||
* from BIOS, and userspace/firmware itself can change
|
* from BIOS, and userspace/firmware itself can change
|
||||||
|
|
@ -859,6 +873,10 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types
|
||||||
* Thus we can only provide write-only access for now.
|
* Thus we can only provide write-only access for now.
|
||||||
*/
|
*/
|
||||||
return 0200;
|
return 0200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->fan[channel] && data->i8k_fan_max < I8K_FAN_AUTO)
|
||||||
|
return 0644;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -928,14 +946,28 @@ static int dell_smm_read(struct device *dev, enum hwmon_sensor_types type, u32 a
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case hwmon_pwm:
|
case hwmon_pwm:
|
||||||
switch (attr) {
|
|
||||||
case hwmon_pwm_input:
|
|
||||||
ret = i8k_get_fan_status(data, channel);
|
ret = i8k_get_fan_status(data, channel);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
switch (attr) {
|
||||||
|
case hwmon_pwm_input:
|
||||||
|
/*
|
||||||
|
* A fan state bigger than i8k_fan_max might indicate that
|
||||||
|
* the fan is currently in automatic mode.
|
||||||
|
*/
|
||||||
|
if (ret > data->i8k_fan_max)
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
*val = clamp_val(ret * data->i8k_pwm_mult, 0, 255);
|
*val = clamp_val(ret * data->i8k_pwm_mult, 0, 255);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case hwmon_pwm_enable:
|
||||||
|
if (ret == I8K_FAN_AUTO)
|
||||||
|
*val = 2;
|
||||||
|
else
|
||||||
|
*val = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -1022,16 +1054,32 @@ static int dell_smm_write(struct device *dev, enum hwmon_sensor_types type, u32
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case hwmon_pwm_enable:
|
case hwmon_pwm_enable:
|
||||||
if (!val)
|
switch (val) {
|
||||||
return -EINVAL;
|
case 1:
|
||||||
|
|
||||||
if (val == 1)
|
|
||||||
enable = false;
|
enable = false;
|
||||||
else
|
break;
|
||||||
|
case 2:
|
||||||
enable = true;
|
enable = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock(&data->i8k_mutex);
|
mutex_lock(&data->i8k_mutex);
|
||||||
|
if (auto_fan) {
|
||||||
err = i8k_enable_fan_auto_mode(data, enable);
|
err = i8k_enable_fan_auto_mode(data, enable);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* When putting the fan into manual control mode we have to ensure
|
||||||
|
* that the device does not overheat until the userspace fan control
|
||||||
|
* software takes over. Because of this we set the fan speed to
|
||||||
|
* i8k_fan_max when disabling automatic fan control.
|
||||||
|
*/
|
||||||
|
if (enable)
|
||||||
|
err = i8k_set_fan(data, channel, I8K_FAN_AUTO);
|
||||||
|
else
|
||||||
|
err = i8k_set_fan(data, channel, data->i8k_fan_max);
|
||||||
|
}
|
||||||
mutex_unlock(&data->i8k_mutex);
|
mutex_unlock(&data->i8k_mutex);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -1082,9 +1130,9 @@ static const struct hwmon_channel_info * const dell_smm_info[] = {
|
||||||
),
|
),
|
||||||
HWMON_CHANNEL_INFO(pwm,
|
HWMON_CHANNEL_INFO(pwm,
|
||||||
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
|
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
|
||||||
HWMON_PWM_INPUT,
|
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
|
||||||
HWMON_PWM_INPUT,
|
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
|
||||||
HWMON_PWM_INPUT
|
HWMON_PWM_INPUT | HWMON_PWM_ENABLE
|
||||||
),
|
),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
#define I8K_FAN_LOW 1
|
#define I8K_FAN_LOW 1
|
||||||
#define I8K_FAN_HIGH 2
|
#define I8K_FAN_HIGH 2
|
||||||
#define I8K_FAN_TURBO 3
|
#define I8K_FAN_TURBO 3
|
||||||
|
/* Many machines treat this mode as some sort of automatic mode */
|
||||||
|
#define I8K_FAN_AUTO 3
|
||||||
#define I8K_FAN_MAX I8K_FAN_TURBO
|
#define I8K_FAN_MAX I8K_FAN_TURBO
|
||||||
|
|
||||||
#define I8K_VOL_UP 1
|
#define I8K_VOL_UP 1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue