From e3703a95c17320a5700b8da28e6961c008684e0e Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 8 Jan 2023 16:27:55 +0100 Subject: [PATCH 1/5] Accept all PWM values for pump duty --- nzxt-kraken3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nzxt-kraken3.c b/nzxt-kraken3.c index e1c411c..7a0b62e 100644 --- a/nzxt-kraken3.c +++ b/nzxt-kraken3.c @@ -37,7 +37,6 @@ static const char *const kraken3_device_names[] = { #define STATUS_VALIDITY (4 * STATUS_INTERVAL) /* seconds */ #define CUSTOM_CURVE_POINTS 40 /* For temps from 20C to 59C (critical temp) */ #define PUMP_DUTY_MIN 20 /* In percent */ -#define CURVE_DUTY_MAX 100 /* In percent */ /* Sensor report offsets for Kraken X53 and Z53 */ #define TEMP_SENSOR_START_OFFSET 15 @@ -197,9 +196,9 @@ static int kraken3_pwm_to_percent(long val, int channel) percent_value = DIV_ROUND_CLOSEST(val * 100, 255); - /* Pump has a minimum duty value in addition to the max */ - if ((channel == 0 && percent_value < PUMP_DUTY_MIN) || percent_value > CURVE_DUTY_MAX) - return -EINVAL; + /* Bring up pump duty to min value if needed */ + if (channel == 0 && percent_value < PUMP_DUTY_MIN) + percent_value = PUMP_DUTY_MIN; return percent_value; } From 056a6af5265d61ab6ae9967ce686e0af9218d1c1 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 8 Jan 2023 19:32:22 +0100 Subject: [PATCH 2/5] Report written PWM duty until sensor report overwrites it --- nzxt-kraken3.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/nzxt-kraken3.c b/nzxt-kraken3.c index 7a0b62e..5d1cf75 100644 --- a/nzxt-kraken3.c +++ b/nzxt-kraken3.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define USB_VENDOR_ID_NZXT 0x1e71 @@ -82,10 +83,21 @@ static const char *const kraken3_fan_label[] = { struct kraken3_channel_info { enum pwm_enable mode; - u16 fixed_duty; + + /* Both values are PWM */ + u16 reported_duty; + u16 fixed_duty; /* Manually set fixed duty */ + u8 pwm_points[CUSTOM_CURVE_POINTS]; }; +/* + * Used for disabling report interrupts when writing PWM values to device + * so that they are reported as written until the next interrupt. This is + * needed for userspace utilities to continue to function + */ +static DEFINE_SPINLOCK(pwm_write_lock); + struct kraken3_data { struct hid_device *hdev; struct device *hwmon_dev; @@ -100,7 +112,6 @@ struct kraken3_data { /* Sensor values */ s32 temp_input[1]; u16 fan_input[2]; - u8 duty_input[2]; enum kinds kind; u8 firmware_version[3]; @@ -237,7 +248,7 @@ static int kraken3_read(struct device *dev, enum hwmon_sensor_types type, u32 at *val = priv->channel_info[channel].mode; break; case hwmon_pwm_input: - *val = kraken3_percent_to_pwm(priv->duty_input[channel]); + *val = priv->channel_info[channel].reported_duty; break; default: break; @@ -288,12 +299,12 @@ static int kraken3_write_curve(struct kraken3_data *priv, u8 *curve_array, int c static int kraken3_write_fixed_duty(struct kraken3_data *priv, long val, int channel) { - int ret, percent_value, i; + int ret, percent_val, i; u8 fixed_curve_points[CUSTOM_CURVE_POINTS]; - percent_value = kraken3_pwm_to_percent(val, channel); - if (percent_value < 0) - return percent_value; + percent_val = kraken3_pwm_to_percent(val, channel); + if (percent_val < 0) + return percent_val; /* * The devices can only control the duty through a curve. @@ -305,7 +316,7 @@ static int kraken3_write_fixed_duty(struct kraken3_data *priv, long val, int cha /* Fill the custom curve with the fixed value we're setting */ for (i = 0; i < CUSTOM_CURVE_POINTS - 1; i++) - fixed_curve_points[i] = percent_value; + fixed_curve_points[i] = percent_val; /* Force duty to 100% at critical temp */ fixed_curve_points[CUSTOM_CURVE_POINTS - 1] = 100; @@ -332,6 +343,16 @@ static int kraken3_write(struct device *dev, enum hwmon_sensor_types type, u32 a ret = kraken3_write_fixed_duty(priv, val, channel); if (ret < 0) return ret; + + /* + * Lock onto this value and report it until next interrupt status + * report is received, so userspace tools can continue to work + * + * TODO: X53 only for now + */ + spin_lock_bh(&pwm_write_lock); + priv->channel_info[channel].reported_duty = val; + spin_unlock_bh(&pwm_write_lock); } break; case hwmon_pwm_enable: @@ -665,12 +686,12 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report, data[TEMP_SENSOR_START_OFFSET] * 1000 + data[TEMP_SENSOR_END_OFFSET] * 100; priv->fan_input[0] = get_unaligned_le16(data + PUMP_SPEED_OFFSET); - priv->duty_input[0] = data[PUMP_DUTY_OFFSET]; + priv->channel_info[0].reported_duty = kraken3_percent_to_pwm(data[PUMP_DUTY_OFFSET]); /* Additional readings for Z53 */ if (priv->kind == Z53) { priv->fan_input[1] = get_unaligned_le16(data + Z53_FAN_SPEED_OFFSET); - priv->duty_input[1] = data[Z53_FAN_DUTY_OFFSET]; + priv->channel_info[1].reported_duty = kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]); complete(&priv->z53_status_processed); } From 5c5a0f88b65c3695a1e4f1d9e6441baf29be4a60 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 8 Jan 2023 19:35:31 +0100 Subject: [PATCH 3/5] Request Z53 status report only when needed --- nzxt-kraken3.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/nzxt-kraken3.c b/nzxt-kraken3.c index 5d1cf75..6d0410c 100644 --- a/nzxt-kraken3.c +++ b/nzxt-kraken3.c @@ -220,20 +220,25 @@ static int kraken3_read(struct device *dev, enum hwmon_sensor_types type, u32 at int ret; struct kraken3_data *priv = dev_get_drvdata(dev); - if (priv->kind == Z53) { - /* Request status on demand */ - reinit_completion(&priv->z53_status_processed); - - /* Send command for getting status */ - ret = kraken3_write_expanded(priv, z53_get_status_cmd, Z53_GET_STATUS_CMD_LENGTH); - if (ret < 0) - return ret; - - wait_for_completion(&priv->z53_status_processed); + if (time_after(jiffies, priv->updated + STATUS_VALIDITY * HZ)) { + if (priv->kind == Z53) { + /* Request status on demand */ + reinit_completion(&priv->z53_status_processed); + + /* Send command for getting status */ + ret = kraken3_write_expanded(priv, z53_get_status_cmd, + Z53_GET_STATUS_CMD_LENGTH); + if (ret < 0) + return ret; + + wait_for_completion(&priv->z53_status_processed); + } else { + return -ENODATA; + } } - if (time_after(jiffies, priv->updated + STATUS_VALIDITY * HZ)) - return -ENODATA; + //if (time_after(jiffies, priv->updated + STATUS_VALIDITY * HZ)) + // return -ENODATA; switch (type) { case hwmon_temp: From 7d6ce4d3934b882e15d21b2bd2bebfbdf464e693 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 8 Jan 2023 19:37:06 +0100 Subject: [PATCH 4/5] Reformat code and remove TODO comment --- nzxt-kraken3.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/nzxt-kraken3.c b/nzxt-kraken3.c index 6d0410c..1cd7c61 100644 --- a/nzxt-kraken3.c +++ b/nzxt-kraken3.c @@ -86,7 +86,7 @@ struct kraken3_channel_info { /* Both values are PWM */ u16 reported_duty; - u16 fixed_duty; /* Manually set fixed duty */ + u16 fixed_duty; /* Manually set fixed duty */ u8 pwm_points[CUSTOM_CURVE_POINTS]; }; @@ -237,9 +237,6 @@ static int kraken3_read(struct device *dev, enum hwmon_sensor_types type, u32 at } } - //if (time_after(jiffies, priv->updated + STATUS_VALIDITY * HZ)) - // return -ENODATA; - switch (type) { case hwmon_temp: *val = priv->temp_input[channel]; @@ -352,8 +349,6 @@ static int kraken3_write(struct device *dev, enum hwmon_sensor_types type, u32 a /* * Lock onto this value and report it until next interrupt status * report is received, so userspace tools can continue to work - * - * TODO: X53 only for now */ spin_lock_bh(&pwm_write_lock); priv->channel_info[channel].reported_duty = val; @@ -429,9 +424,8 @@ static ssize_t kraken3_fan_curve_pwm_store(struct device *dev, struct device_att if (priv->channel_info[dev_attr->nr].mode == curve) { /* Apply the curve */ ret = - kraken3_write_curve(priv, - priv->channel_info[dev_attr->nr].pwm_points, - dev_attr->nr); + kraken3_write_curve(priv, + priv->channel_info[dev_attr->nr].pwm_points, dev_attr->nr); if (ret < 0) return ret; } @@ -696,7 +690,8 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report, /* Additional readings for Z53 */ if (priv->kind == Z53) { priv->fan_input[1] = get_unaligned_le16(data + Z53_FAN_SPEED_OFFSET); - priv->channel_info[1].reported_duty = kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]); + priv->channel_info[1].reported_duty = + kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]); complete(&priv->z53_status_processed); } From 98fc9ed048db3689ca8ea586f0360a9b06a83fa2 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Mon, 9 Jan 2023 21:59:30 +0100 Subject: [PATCH 5/5] Remove the spinlock --- nzxt-kraken3.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/nzxt-kraken3.c b/nzxt-kraken3.c index 1cd7c61..bfd9492 100644 --- a/nzxt-kraken3.c +++ b/nzxt-kraken3.c @@ -91,13 +91,6 @@ struct kraken3_channel_info { u8 pwm_points[CUSTOM_CURVE_POINTS]; }; -/* - * Used for disabling report interrupts when writing PWM values to device - * so that they are reported as written until the next interrupt. This is - * needed for userspace utilities to continue to function - */ -static DEFINE_SPINLOCK(pwm_write_lock); - struct kraken3_data { struct hid_device *hdev; struct device *hwmon_dev; @@ -350,9 +343,7 @@ static int kraken3_write(struct device *dev, enum hwmon_sensor_types type, u32 a * Lock onto this value and report it until next interrupt status * report is received, so userspace tools can continue to work */ - spin_lock_bh(&pwm_write_lock); priv->channel_info[channel].reported_duty = val; - spin_unlock_bh(&pwm_write_lock); } break; case hwmon_pwm_enable: