Skip to content

Commit

Permalink
nzxt-kraken3: Protect completions in raw event parsing with main spin…
Browse files Browse the repository at this point in the history
…lock

Through hidraw, userspace can cause a status report to be sent
from the device. The parsing in kraken3_raw_event() may happen in
parallel to a kraken3_get_status() call (which resets the completion
for tracking the report) if it's running on a different CPU where
bottom half interrupts are not disabled.

Add spin_lock() calls around the completions to prevent race issues.

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git/commit/drivers/hwmon/gigabyte_waterforce.c?h=hwmon-next&id=41c71105a845ec1458680f01644d032a5fbbe0d9

While at it, wrap the Z53 complete_all() with a completion_done().

Signed-off-by: Aleksa Savic <[email protected]>
  • Loading branch information
aleksamagicka committed Jan 10, 2024
1 parent 9a9911e commit 2069218
Showing 1 changed file with 10 additions and 6 deletions.
16 changes: 10 additions & 6 deletions nzxt-kraken3.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,10 +750,12 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report,
* Mark first X-series device report as received,
* as well as all for Z-series, if faulty.
*/
spin_lock(&priv->status_completion_lock);
if (priv->kind != X53 || !completion_done(&priv->status_report_processed)) {
priv->is_device_faulty = true;
complete_all(&priv->status_report_processed);
}
spin_unlock(&priv->status_completion_lock);

return 0;
}
Expand All @@ -768,18 +770,20 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report,
priv->fan_input[0] = get_unaligned_le16(data + PUMP_SPEED_OFFSET);
priv->channel_info[0].reported_duty = kraken3_percent_to_pwm(data[PUMP_DUTY_OFFSET]);

/* Mark first X-series device report as received */
if (priv->kind == X53 && !completion_done(&priv->status_report_processed))
spin_lock(&priv->status_completion_lock);
if (priv->kind == X53 && !completion_done(&priv->status_report_processed)) {
/* Mark first X-series device report as received */
complete_all(&priv->status_report_processed);

/* Additional readings for Z53 */
if (priv->kind == Z53) {
} else if (priv->kind == Z53) {
/* Additional readings for 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]);

complete_all(&priv->status_report_processed);
if (!completion_done(&priv->status_report_processed))
complete_all(&priv->status_report_processed);
}
spin_unlock(&priv->status_completion_lock);

priv->updated = jiffies;

Expand Down

0 comments on commit 2069218

Please sign in to comment.