diff --git a/aquacomputer_d5next.c b/aquacomputer_d5next.c index 5030286..f783689 100644 --- a/aquacomputer_d5next.c +++ b/aquacomputer_d5next.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,8 @@ static const char *const aqc_device_names[] = { #define CTRL_REPORT_ID 0x03 #define AQUAERO_CTRL_REPORT_ID 0x0b +#define CTRL_REPORT_WRITE_DELAY 200 /* ms */ + /* * The HID report that the official software always sends * after writing values, same for all devices, except Aquaero @@ -661,6 +664,9 @@ struct aqc_data { int secondary_ctrl_report_size; u8 *secondary_ctrl_report; + ktime_t last_ctrl_report_write; + int ctrl_report_write_delay; /* Delay between two ctrl report writes, in ms */ + int buffer_size; /* * Used for writing reports (where supported) and reading @@ -812,6 +818,17 @@ static int aqc_send_ctrl_data(struct aqc_data *priv) int ret; u16 checksum; + /* + * If previous write is too close to this one, delay the current write to give + * enough time to the device to process the previous operation. + */ + if (priv->ctrl_report_write_delay) { + s64 delta = ktime_us_delta(ktime_get(), priv->last_ctrl_report_write); + + if (delta < priv->ctrl_report_write_delay) + msleep(priv->ctrl_report_write_delay - delta); + } + /* Checksum is not needed for Aquaero and Aquastream XT */ if (priv->kind != aquaero && priv->kind != aquastreamxt) { /* Init and xorout value for CRC-16/USB is 0xffff */ @@ -837,27 +854,7 @@ static int aqc_send_ctrl_data(struct aqc_data *priv) if (ret < 0) return ret; - /* - * Wait 200ms before returning to make sure that the device actually processed both reports - * and saved ctrl data to memory. Otherwise, an aqc_get_ctrl_data() call made shortly after - * may fail with -EPIPE because the device is still busy and can't provide data. This can - * happen when userspace tools, such as fancontrol or liquidctl, write to sysfs entries in - * quick succession (for example, setting pwmX_enable and pwmX attributes at once). - * - * 200ms was found to be the sweet spot between fixing the issue and not significantly - * prolonging the call. Quadro, Octo, D5 Next and Aquaero are currently known to be - * affected. - */ - switch (priv->kind) { - case quadro: - case octo: - case d5next: - case aquaero: - msleep(200); - break; - default: - break; - } + priv->last_ctrl_report_write = ktime_get(); return ret; } @@ -2817,6 +2814,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; + priv->ctrl_report_write_delay = CTRL_REPORT_WRITE_DELAY; priv->temp_label = label_temp_sensors; priv->virtual_temp_label = label_virtual_temp_sensors; @@ -2847,6 +2845,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->power_cycle_count_offset = AQC_POWER_CYCLES; priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; + priv->ctrl_report_write_delay = CTRL_REPORT_WRITE_DELAY; priv->temp_label = label_d5next_temp; priv->virtual_temp_label = label_virtual_temp_sensors; @@ -2902,6 +2901,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->power_cycle_count_offset = AQC_POWER_CYCLES; priv->buffer_size = OCTO_CTRL_REPORT_SIZE; priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; + priv->ctrl_report_write_delay = CTRL_REPORT_WRITE_DELAY; priv->temp_label = label_temp_sensors; priv->virtual_temp_label = label_virtual_temp_sensors; @@ -2931,6 +2931,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->power_cycle_count_offset = AQC_POWER_CYCLES; priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; + priv->ctrl_report_write_delay = CTRL_REPORT_WRITE_DELAY; priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;