From: Vicki Pfau <vi@endrift.com>
To: Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>,
linux-input@vger.kernel.org
Cc: Vicki Pfau <vi@endrift.com>
Subject: [PATCH 4/5] HID: steam: Clean up locking
Date: Tue, 4 Aug 2026 18:51:05 -0700 [thread overview]
Message-ID: <20260805015116.3884465-5-vi@endrift.com> (raw)
In-Reply-To: <20260805015116.3884465-1-vi@endrift.com>
This cleans up several issues with locking behavior, including RCU accesses
not being guarded behind a lock.
Signed-off-by: Vicki Pfau <vi@endrift.com>
---
drivers/hid/hid-steam.c | 86 ++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 43 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index 2d60b79441b6..87af4bee9f5f 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -632,7 +632,6 @@ static int steam_exchange_report(struct steam_device *steam, u8 *cmd, int csize,
unsigned int retries = 5;
int ret;
- guard(mutex)(&steam->report_mutex);
do {
ret = steam_send_report(steam, cmd, csize);
if (ret < 0)
@@ -728,7 +727,6 @@ static int steam_get_conn_status(struct steam_device *steam)
else
report_id = 0;
- guard(mutex)(&steam->report_mutex);
ret = steam_send_report_id(steam, cmd, sizeof(cmd), report_id);
if (ret < 0)
return ret;
@@ -786,7 +784,6 @@ static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad,
report[8] = count >> 8;
report[9] = gain;
- guard(mutex)(&steam->report_mutex);
ret = steam_send_report(steam, report, 10);
}
@@ -828,7 +825,6 @@ static inline int steam_haptic_rumble(struct steam_device *steam,
report[9] = left_gain;
report[10] = right_gain;
- guard(mutex)(&steam->report_mutex);
ret = steam_send_report(steam, report, sizeof(report));
}
return ret;
@@ -839,8 +835,10 @@ static void steam_haptic_rumble_cb(struct work_struct *work)
struct steam_device *steam = container_of(work, struct steam_device,
rumble_work);
+ mutex_lock(&steam->report_mutex);
steam_haptic_rumble(steam, 0, steam->rumble_left,
steam->rumble_right, 2, 0);
+ mutex_unlock(&steam->report_mutex);
}
static void steam_coalesce_rumble_cb(struct work_struct *work)
@@ -849,8 +847,10 @@ static void steam_coalesce_rumble_cb(struct work_struct *work)
struct steam_device,
coalesce_rumble_work);
+ mutex_lock(&steam->report_mutex);
steam_haptic_rumble(steam, 0, steam->rumble_left,
steam->rumble_right, 2, 0);
+ mutex_unlock(&steam->report_mutex);
if (steam->rumble_left || steam->rumble_right)
schedule_delayed_work(&steam->coalesce_rumble_work, HZ / 20);
@@ -882,7 +882,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
if (steam->gamepad_mode)
enable = false;
- mutex_lock(&steam->report_mutex);
if (enable) {
/* enable esc, enter, cursors */
steam_send_report_byte(steam, ID_SET_DEFAULT_DIGITAL_MAPPINGS);
@@ -905,14 +904,13 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */
0);
}
- mutex_unlock(&steam->report_mutex);
}
static int steam_input_open(struct input_dev *dev)
{
struct steam_device *steam = input_get_drvdata(dev);
unsigned long flags;
- bool set_lizard_mode;
+ bool client_opened;
/*
* Disabling lizard mode automatically is only done on the Steam
@@ -921,9 +919,10 @@ static int steam_input_open(struct input_dev *dev)
*/
if (!(steam->quirks & (STEAM_QUIRK_DECK | STEAM_QUIRK_IBEX))) {
spin_lock_irqsave(&steam->lock, flags);
- set_lizard_mode = !steam->client_opened && lizard_mode;
+ client_opened = steam->client_opened;
spin_unlock_irqrestore(&steam->lock, flags);
- if (set_lizard_mode)
+ guard(mutex)(&steam->report_mutex);
+ if (!client_opened && lizard_mode)
steam_set_lizard_mode(steam, false);
}
@@ -934,13 +933,14 @@ static void steam_input_close(struct input_dev *dev)
{
struct steam_device *steam = input_get_drvdata(dev);
unsigned long flags;
- bool set_lizard_mode;
+ bool client_opened;
if (!(steam->quirks & (STEAM_QUIRK_DECK | STEAM_QUIRK_IBEX))) {
spin_lock_irqsave(&steam->lock, flags);
- set_lizard_mode = !steam->client_opened && lizard_mode;
+ client_opened = steam->client_opened;
spin_unlock_irqrestore(&steam->lock, flags);
- if (set_lizard_mode)
+ guard(mutex)(&steam->report_mutex);
+ if (!client_opened && lizard_mode)
steam_set_lizard_mode(steam, true);
}
}
@@ -948,14 +948,11 @@ static void steam_input_close(struct input_dev *dev)
static int steam_sensor_open(struct input_dev *dev)
{
struct steam_device *steam = input_get_drvdata(dev);
- unsigned long flags;
- bool client_opened;
- spin_lock_irqsave(&steam->lock, flags);
- client_opened = steam->client_opened;
- spin_unlock_irqrestore(&steam->lock, flags);
- if (client_opened)
- return 0;
+ scoped_guard(spinlock_irqsave, &steam->lock) {
+ if (steam->client_opened)
+ return 0;
+ }
guard(mutex)(&steam->report_mutex);
steam_write_settings(steam, SETTING_IMU_MODE,
@@ -968,14 +965,11 @@ static int steam_sensor_open(struct input_dev *dev)
static void steam_sensor_close(struct input_dev *dev)
{
struct steam_device *steam = input_get_drvdata(dev);
- unsigned long flags;
- bool client_opened;
- spin_lock_irqsave(&steam->lock, flags);
- client_opened = steam->client_opened;
- spin_unlock_irqrestore(&steam->lock, flags);
- if (client_opened)
- return;
+ scoped_guard(spinlock_irqsave, &steam->lock) {
+ if (steam->client_opened)
+ return;
+ }
guard(mutex)(&steam->report_mutex);
steam_write_settings(steam, SETTING_IMU_MODE, 0, 0);
@@ -1460,6 +1454,7 @@ static void steam_work_connect_cb(struct work_struct *work)
bool opened;
int ret;
+ guard(mutex)(&steam->report_mutex);
spin_lock_irqsave(&steam->lock, flags);
opened = steam->client_opened;
connected = steam->connected;
@@ -1482,23 +1477,28 @@ static void steam_mode_switch_cb(struct work_struct *work)
struct steam_device, mode_switch);
unsigned long flags;
bool client_opened;
+ bool gamepad_mode;
+
if (!lizard_mode)
return;
+ spin_lock_irqsave(&steam->lock, flags);
steam->gamepad_mode = !steam->gamepad_mode;
+ gamepad_mode = steam->gamepad_mode;
+ client_opened = steam->client_opened;
+ spin_unlock_irqrestore(&steam->lock, flags);
+
+ guard(mutex)(&steam->report_mutex);
hid_dbg(steam->hdev, "%s: switching gamepad mode to %i\n", __func__, steam->gamepad_mode);
- if (steam->gamepad_mode)
+ if (gamepad_mode)
steam_set_lizard_mode(steam, false);
else {
- spin_lock_irqsave(&steam->lock, flags);
- client_opened = steam->client_opened;
- spin_unlock_irqrestore(&steam->lock, flags);
if (!client_opened)
steam_set_lizard_mode(steam, lizard_mode);
}
steam_haptic_pulse(steam, STEAM_PAD_RIGHT, 0x190, 0, 1, 0);
- if (steam->gamepad_mode) {
+ if (gamepad_mode) {
steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x14D, 0x14D, 0x2D, 0);
} else {
steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x1F4, 0x1F4, 0x1E, 0);
@@ -1728,7 +1728,9 @@ static int steam_probe(struct hid_device *hdev,
steam->connected = true;
}
if (steam->connected) {
+ mutex_lock(&steam->report_mutex);
ret = steam_register(steam);
+ mutex_unlock(&steam->report_mutex);
if (ret) {
hid_err(hdev,
"%s:steam_register failed with error %d\n",
@@ -1787,19 +1789,17 @@ static void steam_remove(struct hid_device *hdev)
if (steam->quirks & STEAM_QUIRK_WIRELESS) {
hid_info(hdev, "Steam wireless receiver disconnected");
}
+ guard(mutex)(&steam->report_mutex);
steam_unregister(steam);
hid_hw_stop(hdev);
}
static void steam_do_connect_event(struct steam_device *steam, bool connected)
{
- unsigned long flags;
bool changed;
- spin_lock_irqsave(&steam->lock, flags);
changed = steam->connected != connected;
steam->connected = connected;
- spin_unlock_irqrestore(&steam->lock, flags);
if (changed && schedule_work(&steam->work_connect) == 0)
dbg_hid("%s: connected=%d event already queued\n",
@@ -2228,8 +2228,6 @@ static void steam_do_deck_sensors_event(struct steam_device *steam,
static void steam_do_battery_event(struct steam_device *steam,
struct power_supply *battery, u8 *data)
{
- unsigned long flags;
-
s16 volts = steam_le16(data + 12);
u8 batt = data[14];
@@ -2237,10 +2235,8 @@ static void steam_do_battery_event(struct steam_device *steam,
rcu_read_lock();
battery = rcu_dereference(steam->battery);
if (likely(battery)) {
- spin_lock_irqsave(&steam->lock, flags);
steam->battery_voltage = volts;
steam->battery_charge = batt;
- spin_unlock_irqrestore(&steam->lock, flags);
power_supply_changed(battery);
}
rcu_read_unlock();
@@ -2425,15 +2421,12 @@ static void steam_do_ibex_battery_event(struct steam_device *steam,
struct power_supply *battery,
const struct steam_ibex_battery_status *data)
{
- unsigned long flags;
-
/* Creating the battery may have failed */
guard(rcu)();
battery = rcu_dereference(steam->battery);
if (!likely(battery))
return;
- spin_lock_irqsave(&steam->lock, flags);
steam->battery_voltage = get_unaligned_le16(&data->battery_voltage);
steam->battery_current = get_unaligned_le16(&data->battery_current);
steam->battery_temp = get_unaligned_le16(&data->temperature);
@@ -2452,7 +2445,6 @@ static void steam_do_ibex_battery_event(struct steam_device *steam,
steam->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
break;
}
- spin_unlock_irqrestore(&steam->lock, flags);
power_supply_changed(battery);
}
@@ -2468,6 +2460,7 @@ static int steam_raw_event(struct hid_device *hdev,
if (!steam)
return 0;
+ guard(spinlock_irqsave)(&steam->lock);
if (steam->client_opened)
hid_input_report(steam->client_hdev, report->type, data, size, 0);
@@ -2631,6 +2624,8 @@ static int steam_param_set_lizard_mode(const char *val,
{
struct steam_device *steam;
int ret;
+ bool client_opened;
+ unsigned long flags;
ret = param_set_bool(val, kp);
if (ret)
@@ -2638,8 +2633,13 @@ static int steam_param_set_lizard_mode(const char *val,
mutex_lock(&steam_devices_lock);
list_for_each_entry(steam, &steam_devices, list) {
- if (!steam->client_opened)
+ spin_lock_irqsave(&steam->lock, flags);
+ client_opened = steam->client_opened;
+ spin_unlock_irqrestore(&steam->lock, flags);
+ if (client_opened) {
+ guard(mutex)(&steam->report_mutex);
steam_set_lizard_mode(steam, lizard_mode);
+ }
}
mutex_unlock(&steam_devices_lock);
return 0;
--
2.54.0
next prev parent reply other threads:[~2026-08-05 1:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 1:51 [PATCH 0/5] HID: steam: Add 2026 Steam Controller support Vicki Pfau
2026-08-05 1:51 ` [PATCH 1/5] HID: steam: Initial " Vicki Pfau
2026-08-05 2:13 ` sashiko-bot
2026-08-05 1:51 ` [PATCH 2/5] HID: steam: Fix wording of connect/disconnect logs Vicki Pfau
2026-08-05 2:02 ` sashiko-bot
2026-08-05 1:51 ` [PATCH 3/5] HID: steam: Don't set feature reports when disconnecting Vicki Pfau
2026-08-05 1:51 ` Vicki Pfau [this message]
2026-08-05 2:16 ` [PATCH 4/5] HID: steam: Clean up locking sashiko-bot
2026-08-05 1:51 ` [PATCH 5/5] HID: steam: Zero out inputs when disabling gamepad mode Vicki Pfau
2026-08-05 2:09 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260805015116.3884465-5-vi@endrift.com \
--to=vi@endrift.com \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.