Skip to content

Commit 448b3fe

Browse files
committed
Merge tag 'hwmon-for-v6.9-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon fixes from Guenter Roeck: - pmbus/ucd9000: Increase chip access delay to avoid random access errors - corsair-cpro: Protect kernel code against parallel hidraw access from userspace * tag 'hwmon-for-v6.9-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: hwmon: (pmbus/ucd9000) Increase delay from 250 to 500us hwmon: (corsair-cpro) Protect ccp->wait_input_report with a spinlock hwmon: (corsair-cpro) Use complete_all() instead of complete() in ccp_raw_event() hwmon: (corsair-cpro) Use a separate buffer for sending commands
2 parents 8c3b756 + 26e8383 commit 448b3fe

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

drivers/hwmon/corsair-cpro.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/module.h>
1717
#include <linux/mutex.h>
1818
#include <linux/slab.h>
19+
#include <linux/spinlock.h>
1920
#include <linux/types.h>
2021

2122
#define USB_VENDOR_ID_CORSAIR 0x1b1c
@@ -77,8 +78,11 @@
7778
struct ccp_device {
7879
struct hid_device *hdev;
7980
struct device *hwmon_dev;
81+
/* For reinitializing the completion below */
82+
spinlock_t wait_input_report_lock;
8083
struct completion wait_input_report;
8184
struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
85+
u8 *cmd_buffer;
8286
u8 *buffer;
8387
int target[6];
8488
DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
@@ -111,15 +115,23 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2,
111115
unsigned long t;
112116
int ret;
113117

114-
memset(ccp->buffer, 0x00, OUT_BUFFER_SIZE);
115-
ccp->buffer[0] = command;
116-
ccp->buffer[1] = byte1;
117-
ccp->buffer[2] = byte2;
118-
ccp->buffer[3] = byte3;
119-
118+
memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE);
119+
ccp->cmd_buffer[0] = command;
120+
ccp->cmd_buffer[1] = byte1;
121+
ccp->cmd_buffer[2] = byte2;
122+
ccp->cmd_buffer[3] = byte3;
123+
124+
/*
125+
* Disable raw event parsing for a moment to safely reinitialize the
126+
* completion. Reinit is done because hidraw could have triggered
127+
* the raw event parsing and marked the ccp->wait_input_report
128+
* completion as done.
129+
*/
130+
spin_lock_bh(&ccp->wait_input_report_lock);
120131
reinit_completion(&ccp->wait_input_report);
132+
spin_unlock_bh(&ccp->wait_input_report_lock);
121133

122-
ret = hid_hw_output_report(ccp->hdev, ccp->buffer, OUT_BUFFER_SIZE);
134+
ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE);
123135
if (ret < 0)
124136
return ret;
125137

@@ -135,11 +147,12 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8
135147
struct ccp_device *ccp = hid_get_drvdata(hdev);
136148

137149
/* only copy buffer when requested */
138-
if (completion_done(&ccp->wait_input_report))
139-
return 0;
140-
141-
memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
142-
complete(&ccp->wait_input_report);
150+
spin_lock(&ccp->wait_input_report_lock);
151+
if (!completion_done(&ccp->wait_input_report)) {
152+
memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
153+
complete_all(&ccp->wait_input_report);
154+
}
155+
spin_unlock(&ccp->wait_input_report_lock);
143156

144157
return 0;
145158
}
@@ -492,7 +505,11 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
492505
if (!ccp)
493506
return -ENOMEM;
494507

495-
ccp->buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
508+
ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
509+
if (!ccp->cmd_buffer)
510+
return -ENOMEM;
511+
512+
ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL);
496513
if (!ccp->buffer)
497514
return -ENOMEM;
498515

@@ -510,7 +527,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
510527

511528
ccp->hdev = hdev;
512529
hid_set_drvdata(hdev, ccp);
530+
513531
mutex_init(&ccp->mutex);
532+
spin_lock_init(&ccp->wait_input_report_lock);
514533
init_completion(&ccp->wait_input_report);
515534

516535
hid_device_io_start(hdev);

drivers/hwmon/pmbus/ucd9000.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ struct ucd9000_debugfs_entry {
8080
* It has been observed that the UCD90320 randomly fails register access when
8181
* doing another access right on the back of a register write. To mitigate this
8282
* make sure that there is a minimum delay between a write access and the
83-
* following access. The 250us is based on experimental data. At a delay of
84-
* 200us the issue seems to go away. Add a bit of extra margin to allow for
83+
* following access. The 500 is based on experimental data. At a delay of
84+
* 350us the issue seems to go away. Add a bit of extra margin to allow for
8585
* system to system differences.
8686
*/
87-
#define UCD90320_WAIT_DELAY_US 250
87+
#define UCD90320_WAIT_DELAY_US 500
8888

8989
static inline void ucd90320_wait(const struct ucd9000_data *data)
9090
{

0 commit comments

Comments
 (0)