Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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] https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/issues/82

Fixes: 752b927951ea ("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>

authored by

Aleksa Savic and committed by
Guenter Roeck
56b930dc f38963b9

+36 -1
+36 -1
drivers/hwmon/aquacomputer_d5next.c
··· 13 13 14 14 #include <linux/crc16.h> 15 15 #include <linux/debugfs.h> 16 + #include <linux/delay.h> 16 17 #include <linux/hid.h> 17 18 #include <linux/hwmon.h> 18 19 #include <linux/jiffies.h> 20 + #include <linux/ktime.h> 19 21 #include <linux/module.h> 20 22 #include <linux/mutex.h> 21 23 #include <linux/seq_file.h> ··· 64 62 65 63 #define CTRL_REPORT_ID 0x03 66 64 #define AQUAERO_CTRL_REPORT_ID 0x0b 65 + 66 + #define CTRL_REPORT_DELAY 200 /* ms */ 67 67 68 68 /* The HID report that the official software always sends 69 69 * after writing values, currently same for all devices ··· 531 527 int secondary_ctrl_report_size; 532 528 u8 *secondary_ctrl_report; 533 529 530 + ktime_t last_ctrl_report_op; 531 + int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */ 532 + 534 533 int buffer_size; 535 534 u8 *buffer; 536 535 int checksum_start; ··· 618 611 return 0; 619 612 } 620 613 614 + static void aqc_delay_ctrl_report(struct aqc_data *priv) 615 + { 616 + /* 617 + * If previous read or write is too close to this one, delay the current operation 618 + * to give the device enough time to process the previous one. 619 + */ 620 + if (priv->ctrl_report_delay) { 621 + s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op); 622 + 623 + if (delta < priv->ctrl_report_delay) 624 + msleep(priv->ctrl_report_delay - delta); 625 + } 626 + } 627 + 621 628 /* Expects the mutex to be locked */ 622 629 static int aqc_get_ctrl_data(struct aqc_data *priv) 623 630 { 624 631 int ret; 632 + 633 + aqc_delay_ctrl_report(priv); 625 634 626 635 memset(priv->buffer, 0x00, priv->buffer_size); 627 636 ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, 628 637 HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 629 638 if (ret < 0) 630 639 ret = -ENODATA; 640 + 641 + priv->last_ctrl_report_op = ktime_get(); 631 642 632 643 return ret; 633 644 } ··· 655 630 { 656 631 int ret; 657 632 u16 checksum; 633 + 634 + aqc_delay_ctrl_report(priv); 658 635 659 636 /* Checksum is not needed for Aquaero */ 660 637 if (priv->kind != aquaero) { ··· 673 646 ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, 674 647 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 675 648 if (ret < 0) 676 - return ret; 649 + goto record_access_and_ret; 677 650 678 651 /* The official software sends this report after every change, so do it here as well */ 679 652 ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id, 680 653 priv->secondary_ctrl_report, priv->secondary_ctrl_report_size, 681 654 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 655 + 656 + record_access_and_ret: 657 + priv->last_ctrl_report_op = ktime_get(); 658 + 682 659 return ret; 683 660 } 684 661 ··· 1555 1524 1556 1525 priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; 1557 1526 priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; 1527 + priv->ctrl_report_delay = CTRL_REPORT_DELAY; 1558 1528 1559 1529 priv->temp_label = label_temp_sensors; 1560 1530 priv->virtual_temp_label = label_virtual_temp_sensors; ··· 1579 1547 priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; 1580 1548 1581 1549 priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; 1550 + priv->ctrl_report_delay = CTRL_REPORT_DELAY; 1582 1551 1583 1552 priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES; 1584 1553 ··· 1630 1597 priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; 1631 1598 1632 1599 priv->buffer_size = OCTO_CTRL_REPORT_SIZE; 1600 + priv->ctrl_report_delay = CTRL_REPORT_DELAY; 1633 1601 1634 1602 priv->power_cycle_count_offset = OCTO_POWER_CYCLES; 1635 1603 ··· 1658 1624 priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; 1659 1625 1660 1626 priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; 1627 + priv->ctrl_report_delay = CTRL_REPORT_DELAY; 1661 1628 1662 1629 priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET; 1663 1630 priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;