diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c index 6565731b0e71..3d3786c82931 100644 --- a/drivers/hwmon/aquacomputer_d5next.c +++ b/drivers/hwmon/aquacomputer_d5next.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -612,9 +613,9 @@ struct aqc_data { u32 speed_input_min[1]; u32 speed_input_target[1]; u32 speed_input_max[1]; - u32 power_input[8]; + long power_input[8]; u16 voltage_input[8]; - u16 current_input[8]; + u32 current_input[8]; /* Label values */ const char *const *temp_label; @@ -989,7 +990,7 @@ static int aqc_legacy_read(struct aqc_data *priv) /* Calculation derived from linear regression */ sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_CURR_OFFSET); - priv->current_input[0] = DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52; + priv->current_input[0] = max(DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52, 0); sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_VOLTAGE_OFFSET); priv->voltage_input[0] = DIV_ROUND_CLOSEST(sensor_value * 1000, 61); @@ -1019,6 +1020,7 @@ static int aqc_legacy_read(struct aqc_data *priv) static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { + long power; int ret; struct aqc_data *priv = dev_get_drvdata(dev); @@ -1083,7 +1085,10 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, } break; case hwmon_power: - *val = priv->power_input[channel]; + power = READ_ONCE(priv->power_input[channel]); + if (power == -ENODATA) + return -ENODATA; + *val = power; break; case hwmon_pwm: switch (priv->kind) { @@ -1383,9 +1388,9 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 priv->speed_input[i] = get_unaligned_be16(data + priv->fan_sensor_offsets[i] + priv->fan_structure->speed); - priv->power_input[i] = - get_unaligned_be16(data + priv->fan_sensor_offsets[i] + - priv->fan_structure->power) * 10000; + WRITE_ONCE(priv->power_input[i], + get_unaligned_be16(data + priv->fan_sensor_offsets[i] + + priv->fan_structure->power) * 10000); priv->voltage_input[i] = get_unaligned_be16(data + priv->fan_sensor_offsets[i] + priv->fan_structure->voltage) * 10; @@ -1425,7 +1430,8 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 priv->speed_input[2] = get_unaligned_be16(data + AQUASTREAMULT_PRESSURE_OFFSET); priv->speed_input[3] = get_unaligned_be16(data + AQUASTREAMULT_FLOW_SENSOR_OFFSET); - priv->power_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_POWER) * 10000; + WRITE_ONCE(priv->power_input[1], + get_unaligned_be16(data + AQUASTREAMULT_PUMP_POWER) * 10000); priv->voltage_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_VOLTAGE) * 10; @@ -1438,10 +1444,11 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 case highflownext: /* If external temp sensor is not connected, its power reading is also N/A */ if (priv->temp_input[1] == -ENODATA) - priv->power_input[0] = -ENODATA; + WRITE_ONCE(priv->power_input[0], -ENODATA); else - priv->power_input[0] = - get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * 1000000; + WRITE_ONCE(priv->power_input[0], + min_t(u64, get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * + 1000000ULL, LONG_MAX)); priv->voltage_input[0] = get_unaligned_be16(data + HIGHFLOWNEXT_5V_VOLTAGE) * 10; priv->voltage_input[1] =