Skip to content

Commit 56b930d

Browse files
aleksamagickagroeck
authored andcommitted
hwmon: (aquacomputer_d5next) Add selective 200ms delay after sending ctrl report
Add a 200ms delay after sending a ctrl report to Quadro, Octo, D5 Next and Aquaero to give them enough time to process the request and save the data to memory. Otherwise, under heavier userspace loads where multiple sysfs entries are usually set in quick succession, a new ctrl report could be requested from the device while it's still processing the previous one and fail with -EPIPE. The delay is only applied if two ctrl report operations are near each other in time. Reported by a user on Github [1] and tested by both of us. [1] aleksamagicka/aquacomputer_d5next-hwmon#82 Fixes: 752b927 ("hwmon: (aquacomputer_d5next) Add support for Aquacomputer Octo") Signed-off-by: Aleksa Savic <savicaleksa83@gmail.com> Link: https://lore.kernel.org/r/20230807172004.456968-1-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent f38963b commit 56b930d

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

drivers/hwmon/aquacomputer_d5next.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
#include <linux/crc16.h>
1515
#include <linux/debugfs.h>
16+
#include <linux/delay.h>
1617
#include <linux/hid.h>
1718
#include <linux/hwmon.h>
1819
#include <linux/jiffies.h>
20+
#include <linux/ktime.h>
1921
#include <linux/module.h>
2022
#include <linux/mutex.h>
2123
#include <linux/seq_file.h>
@@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = {
6365
#define CTRL_REPORT_ID 0x03
6466
#define AQUAERO_CTRL_REPORT_ID 0x0b
6567

68+
#define CTRL_REPORT_DELAY 200 /* ms */
69+
6670
/* The HID report that the official software always sends
6771
* after writing values, currently same for all devices
6872
*/
@@ -527,6 +531,9 @@ struct aqc_data {
527531
int secondary_ctrl_report_size;
528532
u8 *secondary_ctrl_report;
529533

534+
ktime_t last_ctrl_report_op;
535+
int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */
536+
530537
int buffer_size;
531538
u8 *buffer;
532539
int checksum_start;
@@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
611618
return 0;
612619
}
613620

621+
static void aqc_delay_ctrl_report(struct aqc_data *priv)
622+
{
623+
/*
624+
* If previous read or write is too close to this one, delay the current operation
625+
* to give the device enough time to process the previous one.
626+
*/
627+
if (priv->ctrl_report_delay) {
628+
s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);
629+
630+
if (delta < priv->ctrl_report_delay)
631+
msleep(priv->ctrl_report_delay - delta);
632+
}
633+
}
634+
614635
/* Expects the mutex to be locked */
615636
static int aqc_get_ctrl_data(struct aqc_data *priv)
616637
{
617638
int ret;
618639

640+
aqc_delay_ctrl_report(priv);
641+
619642
memset(priv->buffer, 0x00, priv->buffer_size);
620643
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
621644
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
622645
if (ret < 0)
623646
ret = -ENODATA;
624647

648+
priv->last_ctrl_report_op = ktime_get();
649+
625650
return ret;
626651
}
627652

@@ -631,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
631656
int ret;
632657
u16 checksum;
633658

659+
aqc_delay_ctrl_report(priv);
660+
634661
/* Checksum is not needed for Aquaero */
635662
if (priv->kind != aquaero) {
636663
/* Init and xorout value for CRC-16/USB is 0xffff */
@@ -646,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
646673
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
647674
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
648675
if (ret < 0)
649-
return ret;
676+
goto record_access_and_ret;
650677

651678
/* The official software sends this report after every change, so do it here as well */
652679
ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
653680
priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
654681
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
682+
683+
record_access_and_ret:
684+
priv->last_ctrl_report_op = ktime_get();
685+
655686
return ret;
656687
}
657688

@@ -1524,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
15241555

15251556
priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
15261557
priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
1558+
priv->ctrl_report_delay = CTRL_REPORT_DELAY;
15271559

15281560
priv->temp_label = label_temp_sensors;
15291561
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -1547,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
15471579
priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
15481580

15491581
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
1582+
priv->ctrl_report_delay = CTRL_REPORT_DELAY;
15501583

15511584
priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
15521585

@@ -1597,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
15971630
priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
15981631

15991632
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
1633+
priv->ctrl_report_delay = CTRL_REPORT_DELAY;
16001634

16011635
priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
16021636

@@ -1624,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
16241658
priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
16251659

16261660
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
1661+
priv->ctrl_report_delay = CTRL_REPORT_DELAY;
16271662

16281663
priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
16291664
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;

0 commit comments

Comments
 (0)