Skip to content

Commit b1986c8

Browse files
Wer-Wolfgroeck
authored andcommitted
hwmon: (dell-smm) Add support for fanX_min, fanX_max and fanX_target
The nominal speed of each fan can be obtained with i8k_get_fan_nominal_speed(), however the result is not available from userspace. Change that by adding fanX_min, fanX_max and fanX_target attributes. All are RO since fan control happens over pwm. Tested on a Dell Inspiron 3505 and a Dell Latitude C600. Signed-off-by: Armin Wolf <[email protected]> Reviewed-by: Pali Rohár <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 51369c0 commit b1986c8

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

Documentation/hwmon/dell-smm-hwmon.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Name Perm Description
3434
=============================== ======= =======================================
3535
fan[1-3]_input RO Fan speed in RPM.
3636
fan[1-3]_label RO Fan label.
37+
fan[1-3]_min RO Minimal Fan speed in RPM
38+
fan[1-3]_max RO Maximal Fan speed in RPM
39+
fan[1-3]_target RO Expected Fan speed in RPM
3740
pwm[1-3] RW Control the fan PWM duty-cycle.
3841
pwm1_enable WO Enable or disable automatic BIOS fan
3942
control (not supported on all laptops,

drivers/hwmon/dell-smm-hwmon.c

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct dell_smm_data {
7474
int temp_type[DELL_SMM_NO_TEMP];
7575
bool fan[DELL_SMM_NO_FANS];
7676
int fan_type[DELL_SMM_NO_FANS];
77+
int *fan_nominal_speed[DELL_SMM_NO_FANS];
7778
};
7879

7980
MODULE_AUTHOR("Massimo Dal Zotto ([email protected])");
@@ -671,6 +672,13 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types
671672
if (data->fan[channel] && !data->disallow_fan_type_call)
672673
return 0444;
673674

675+
break;
676+
case hwmon_fan_min:
677+
case hwmon_fan_max:
678+
case hwmon_fan_target:
679+
if (data->fan_nominal_speed[channel])
680+
return 0444;
681+
674682
break;
675683
default:
676684
break;
@@ -738,6 +746,25 @@ static int dell_smm_read(struct device *dev, enum hwmon_sensor_types type, u32 a
738746

739747
*val = ret;
740748

749+
return 0;
750+
case hwmon_fan_min:
751+
*val = data->fan_nominal_speed[channel][0];
752+
753+
return 0;
754+
case hwmon_fan_max:
755+
*val = data->fan_nominal_speed[channel][data->i8k_fan_max];
756+
757+
return 0;
758+
case hwmon_fan_target:
759+
ret = i8k_get_fan_status(data, channel);
760+
if (ret < 0)
761+
return ret;
762+
763+
if (ret > data->i8k_fan_max)
764+
ret = data->i8k_fan_max;
765+
766+
*val = data->fan_nominal_speed[channel][ret];
767+
741768
return 0;
742769
default:
743770
break;
@@ -887,9 +914,12 @@ static const struct hwmon_channel_info *dell_smm_info[] = {
887914
HWMON_T_INPUT | HWMON_T_LABEL
888915
),
889916
HWMON_CHANNEL_INFO(fan,
890-
HWMON_F_INPUT | HWMON_F_LABEL,
891-
HWMON_F_INPUT | HWMON_F_LABEL,
892-
HWMON_F_INPUT | HWMON_F_LABEL
917+
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
918+
HWMON_F_TARGET,
919+
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
920+
HWMON_F_TARGET,
921+
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
922+
HWMON_F_TARGET
893923
),
894924
HWMON_CHANNEL_INFO(pwm,
895925
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
@@ -908,7 +938,7 @@ static int __init dell_smm_init_hwmon(struct device *dev)
908938
{
909939
struct dell_smm_data *data = dev_get_drvdata(dev);
910940
struct device *dell_smm_hwmon_dev;
911-
int i, err;
941+
int i, state, err;
912942

913943
for (i = 0; i < DELL_SMM_NO_TEMP; i++) {
914944
data->temp_type[i] = i8k_get_temp_type(i);
@@ -924,8 +954,27 @@ static int __init dell_smm_init_hwmon(struct device *dev)
924954
err = i8k_get_fan_status(data, i);
925955
if (err < 0)
926956
err = i8k_get_fan_type(data, i);
927-
if (err >= 0)
928-
data->fan[i] = true;
957+
958+
if (err < 0)
959+
continue;
960+
961+
data->fan[i] = true;
962+
data->fan_nominal_speed[i] = devm_kmalloc_array(dev, data->i8k_fan_max + 1,
963+
sizeof(*data->fan_nominal_speed[i]),
964+
GFP_KERNEL);
965+
if (!data->fan_nominal_speed[i])
966+
continue;
967+
968+
for (state = 0; state <= data->i8k_fan_max; state++) {
969+
err = i8k_get_fan_nominal_speed(data, i, state);
970+
if (err < 0) {
971+
/* Mark nominal speed table as invalid in case of error */
972+
devm_kfree(dev, data->fan_nominal_speed[i]);
973+
data->fan_nominal_speed[i] = NULL;
974+
break;
975+
}
976+
data->fan_nominal_speed[i][state] = err;
977+
}
929978
}
930979

931980
dell_smm_hwmon_dev = devm_hwmon_device_register_with_info(dev, "dell_smm", data,

0 commit comments

Comments
 (0)