Skip to content

Commit

Permalink
nzxt-kraken3: Reinit status request completion under a spinlock
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksa Savic <[email protected]>
  • Loading branch information
aleksamagicka committed Oct 16, 2023
1 parent d14d1fe commit 5f8c3c1
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions nzxt-kraken3.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <asm/unaligned.h>

Expand Down Expand Up @@ -117,6 +118,8 @@ struct kraken3_data {
* was processed after requesting one.
*/
struct completion status_report_processed;
/* For locking the above completion */
spinlock_t status_completion_lock;

u8 *buffer;
struct kraken3_channel_info channel_info[2]; /* Pump and fan */
Expand Down Expand Up @@ -256,6 +259,7 @@ static int kraken3_read_z53(struct kraken3_data *priv)
{
int ret;
ulong remaining_time;
unsigned long flags;

/* In the case of multiple concurrent readers, request a status report only if necessary */
if (!mutex_lock_interruptible(&priv->z53_status_request_lock)) {
Expand All @@ -264,6 +268,14 @@ static int kraken3_read_z53(struct kraken3_data *priv)
goto unlock_and_return;
}

/*
* Disable interrupts for a moment to safely reinit the completion,
* as hidraw calls could have allowed one or more readers to complete().
*/
spin_lock_irqsave(&priv->status_completion_lock, flags);
reinit_completion(&priv->status_report_processed);
spin_unlock_irqrestore(&priv->status_completion_lock, flags);

/* Send command for getting status */
ret = kraken3_write_expanded(priv, z53_get_status_cmd, Z53_GET_STATUS_CMD_LENGTH);
if (ret < 0) {
Expand Down Expand Up @@ -726,6 +738,7 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report,
{
int i;
struct kraken3_data *priv = hid_get_drvdata(hdev);
unsigned long flags;

if (size < MIN_REPORT_LENGTH)
return 0;
Expand Down Expand Up @@ -773,7 +786,9 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report,
priv->channel_info[1].reported_duty =
kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]);

spin_lock_irqsave(&priv->status_completion_lock, flags);
complete(&priv->status_report_processed);
spin_unlock_irqrestore(&priv->status_completion_lock, flags);
}

priv->updated = jiffies;
Expand Down Expand Up @@ -915,6 +930,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
init_waitqueue_head(&priv->z53_reader_wq);
init_completion(&priv->fw_version_processed);
init_completion(&priv->status_report_processed);
spin_lock_init(&priv->status_completion_lock);

ret = kraken3_init_device(hdev);
if (ret) {
Expand Down

0 comments on commit 5f8c3c1

Please sign in to comment.