* [STABLE v6.6 2/5] HID: steam: Fully unregister controller when hidraw is opened
2026-10-13 9:11 [STABLE v6.6 1/5] HID: hid-steam: Make client_opened a counter Lee Jones
@ 2026-10-13 9:11 ` Lee Jones
2026-10-13 9:11 ` [STABLE v6.6 3/5] HID: steam: Rearrange teardown sequence Lee Jones
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-10-13 9:11 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
Cc: stable, Vicki Pfau, Jiri Kosina
From: Vicki Pfau <vi@endrift.com>
[ Upstream commit cd33a91d37eb4d7c6ce56aa7f4688066309808eb ]
To avoid conflicts between anything touching the hidraw and the driver we
had previously detached the evdev nodes when the hidraw is opened. However,
this isn't sufficient to avoid FEATURE reports from conflicting, so we
change to fully unregistering the controller internally, leaving only the
hidraw active until it's closed.
This also unifies the unregister and connect callbacks, as now the logic
between these two callbacks is identical.
Signed-off-by: Vicki Pfau <vi@endrift.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Omit coalesce_rumble_work cancellation as 1d4549fd1115 ("HID:
steam: Coalesce rumble packets") is not present]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/hid-steam.c | 73 +++++++++++++++--------------------------
1 file changed, 27 insertions(+), 46 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index d390ac5aee0d..59e39bdf34ed 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -312,7 +312,6 @@ struct steam_device {
u16 rumble_left;
u16 rumble_right;
unsigned int sensor_timestamp_us;
- struct work_struct unregister_work;
};
static int steam_recv_report(struct steam_device *steam,
@@ -694,6 +693,7 @@ static int steam_battery_register(struct steam_device *steam)
&steam->battery_desc, &battery_cfg);
if (IS_ERR(battery)) {
ret = PTR_ERR(battery);
+ devm_kfree(&steam->hdev->dev, steam->battery_desc.name);
hid_err(steam->hdev,
"%s:power_supply_register failed with error %d\n",
__func__, ret);
@@ -947,6 +947,7 @@ static void steam_battery_unregister(struct steam_device *steam)
RCU_INIT_POINTER(steam->battery, NULL);
synchronize_rcu();
power_supply_unregister(battery);
+ devm_kfree(&steam->hdev->dev, steam->battery_desc.name);
}
static int steam_register(struct steam_device *steam)
@@ -954,6 +955,7 @@ static int steam_register(struct steam_device *steam)
int ret;
unsigned long client_opened;
unsigned long flags;
+ bool do_add;
/*
* This function can be called several times in a row with the
@@ -977,10 +979,7 @@ static int steam_register(struct steam_device *steam)
if (steam->quirks & STEAM_QUIRK_WIRELESS)
steam_battery_register(steam);
- mutex_lock(&steam_devices_lock);
- if (list_empty(&steam->list))
- list_add(&steam->list, &steam_devices);
- mutex_unlock(&steam_devices_lock);
+ do_add = true;
}
spin_lock_irqsave(&steam->lock, flags);
@@ -996,6 +995,13 @@ static int steam_register(struct steam_device *steam)
if (ret != 0)
goto steam_register_sensors_fail;
}
+
+ if (do_add) {
+ mutex_lock(&steam_devices_lock);
+ if (list_empty(&steam->list))
+ list_add(&steam->list, &steam_devices);
+ mutex_unlock(&steam_devices_lock);
+ }
return 0;
steam_register_sensors_fail:
@@ -1006,38 +1012,41 @@ static int steam_register(struct steam_device *steam)
static void steam_unregister(struct steam_device *steam)
{
+ if (!steam->serial_no[0])
+ return;
+
+ hid_info(steam->hdev, "Steam Controller '%s' disconnected",
+ steam->serial_no);
steam_battery_unregister(steam);
steam_sensors_unregister(steam);
steam_input_unregister(steam);
- if (steam->serial_no[0]) {
- hid_info(steam->hdev, "Steam Controller '%s' disconnected",
- steam->serial_no);
- mutex_lock(&steam_devices_lock);
- list_del_init(&steam->list);
- mutex_unlock(&steam_devices_lock);
- steam->serial_no[0] = 0;
- }
+ mutex_lock(&steam_devices_lock);
+ list_del_init(&steam->list);
+ mutex_unlock(&steam_devices_lock);
+ steam->serial_no[0] = 0;
}
static void steam_work_connect_cb(struct work_struct *work)
{
struct steam_device *steam = container_of(work, struct steam_device,
work_connect);
+
unsigned long flags;
bool connected;
+ bool opened;
int ret;
spin_lock_irqsave(&steam->lock, flags);
+ opened = steam->client_opened;
connected = steam->connected;
spin_unlock_irqrestore(&steam->lock, flags);
- if (connected) {
+ if (connected && !opened) {
ret = steam_register(steam);
- if (ret) {
+ if (ret)
hid_err(steam->hdev,
"%s:steam_register failed with error %d\n",
__func__, ret);
- }
} else {
steam_unregister(steam);
}
@@ -1071,31 +1080,6 @@ static void steam_mode_switch_cb(struct work_struct *work)
}
}
-static void steam_work_unregister_cb(struct work_struct *work)
-{
- struct steam_device *steam = container_of(work, struct steam_device,
- unregister_work);
- unsigned long flags;
- bool connected;
- bool opened;
-
- spin_lock_irqsave(&steam->lock, flags);
- opened = steam->client_opened;
- connected = steam->connected;
- spin_unlock_irqrestore(&steam->lock, flags);
-
- if (connected) {
- if (opened) {
- steam_sensors_unregister(steam);
- steam_input_unregister(steam);
- } else {
- steam_set_lizard_mode(steam, lizard_mode);
- steam_input_register(steam);
- steam_sensors_register(steam);
- }
- }
-}
-
static bool steam_is_valve_interface(struct hid_device *hdev)
{
struct hid_report_enum *rep_enum;
@@ -1141,7 +1125,7 @@ static int steam_client_ll_open(struct hid_device *hdev)
steam->client_opened++;
spin_unlock_irqrestore(&steam->lock, flags);
- schedule_work(&steam->unregister_work);
+ schedule_work(&steam->work_connect);
return 0;
}
@@ -1158,7 +1142,7 @@ static void steam_client_ll_close(struct hid_device *hdev)
connected = steam->connected && !steam->client_opened;
spin_unlock_irqrestore(&steam->lock, flags);
- schedule_work(&steam->unregister_work);
+ schedule_work(&steam->work_connect);
}
static int steam_client_ll_raw_request(struct hid_device *hdev,
@@ -1250,7 +1234,6 @@ static int steam_probe(struct hid_device *hdev,
INIT_LIST_HEAD(&steam->list);
INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb);
steam->sensor_timestamp_us = 0;
- INIT_WORK(&steam->unregister_work, steam_work_unregister_cb);
/*
* With the real steam controller interface, do not connect hidraw.
@@ -1311,7 +1294,6 @@ static int steam_probe(struct hid_device *hdev,
cancel_work_sync(&steam->work_connect);
cancel_delayed_work_sync(&steam->mode_switch);
cancel_work_sync(&steam->rumble_work);
- cancel_work_sync(&steam->unregister_work);
return ret;
}
@@ -1329,7 +1311,6 @@ static void steam_remove(struct hid_device *hdev)
cancel_delayed_work_sync(&steam->mode_switch);
cancel_work_sync(&steam->work_connect);
cancel_work_sync(&steam->rumble_work);
- cancel_work_sync(&steam->unregister_work);
steam->client_hdev = NULL;
steam->client_opened = 0;
if (steam->quirks & STEAM_QUIRK_WIRELESS) {
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [STABLE v6.6 4/5] HID: steam: Refactor registration
2026-10-13 9:11 [STABLE v6.6 1/5] HID: hid-steam: Make client_opened a counter Lee Jones
2026-10-13 9:11 ` [STABLE v6.6 2/5] HID: steam: Fully unregister controller when hidraw is opened Lee Jones
2026-10-13 9:11 ` [STABLE v6.6 3/5] HID: steam: Rearrange teardown sequence Lee Jones
@ 2026-10-13 9:11 ` Lee Jones
2026-10-13 9:11 ` [STABLE v6.6 5/5] HID: steam: Clean up locking Lee Jones
3 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-10-13 9:11 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
Cc: stable, Vicki Pfau, Jiri Kosina
From: Vicki Pfau <vi@endrift.com>
[ Upstream commit 6f9b740c31ba7e061b2ebb330d9a3d63f1358f29 ]
This refactors and simplifies the registration/unregistration flow. Since
we now only perform registration when the client isn't opened anymore, the
logic for handling that can be removed, and the rest of the function
streamlined.
We also remove the previous assumption that we have a serial number to show
we're registered, replacing it with a single purpose boolean.
In a previous refactor the code for unregistering a battery if later
registration steps failed was accidentally left out. As a result, a
lingering power_supply object could get left over after the steam object
was torn down. This is also fixed here.
Signed-off-by: Vicki Pfau <vi@endrift.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Omit steam_get_attributes() and coalesce_rumble_work cancellation
as a0fbd9437d7d and 1d4549fd1115 are not present]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/hid-steam.c | 70 +++++++++++++++++++----------------------
1 file changed, 32 insertions(+), 38 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index df176a722061..06c2fcd134ce 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -300,6 +300,7 @@ struct steam_device {
unsigned long quirks;
struct work_struct work_connect;
bool connected;
+ bool registered;
char serial_no[STEAM_SERIAL_LEN + 1];
struct power_supply_desc battery_desc;
struct power_supply __rcu *battery;
@@ -953,9 +954,6 @@ static void steam_battery_unregister(struct steam_device *steam)
static int steam_register(struct steam_device *steam)
{
int ret;
- unsigned long client_opened;
- unsigned long flags;
- bool do_add;
/*
* This function can be called several times in a row with the
@@ -963,60 +961,56 @@ static int steam_register(struct steam_device *steam)
* another client send a get_connection_status command, for example.
* The battery and serial number are set just once per device.
*/
- if (!steam->serial_no[0]) {
- /*
- * Unlikely, but getting the serial could fail, and it is not so
- * important, so make up a serial number and go on.
- */
- if (steam_get_serial(steam) < 0)
- strscpy(steam->serial_no, "XXXXXXXXXX",
- sizeof(steam->serial_no));
+ if (steam->registered)
+ return 0;
- hid_info(steam->hdev, "Steam Controller '%s' connected",
- steam->serial_no);
+ /*
+ * Unlikely, but getting the serial could fail, and it is not so
+ * important, so make up a serial number and go on.
+ */
+ if (steam_get_serial(steam) < 0 || !steam->serial_no[0])
+ strscpy(steam->serial_no, "XXXXXXXXXX",
+ sizeof(steam->serial_no));
- /* ignore battery errors, we can live without it */
- if (steam->quirks & STEAM_QUIRK_WIRELESS)
- steam_battery_register(steam);
+ hid_info(steam->hdev, "Steam Controller '%s' connected",
+ steam->serial_no);
- do_add = true;
- }
+ /* ignore battery errors, we can live without it */
+ if (steam->quirks & STEAM_QUIRK_WIRELESS)
+ steam_battery_register(steam);
- spin_lock_irqsave(&steam->lock, flags);
- client_opened = steam->client_opened;
- spin_unlock_irqrestore(&steam->lock, flags);
+ steam_set_lizard_mode(steam, lizard_mode);
+ ret = steam_input_register(steam);
+ if (ret != 0)
+ goto steam_register_input_fail;
+ ret = steam_sensors_register(steam);
+ if (ret != 0)
+ goto steam_register_sensors_fail;
- if (!client_opened) {
- steam_set_lizard_mode(steam, lizard_mode);
- ret = steam_input_register(steam);
- if (ret != 0)
- goto steam_register_input_fail;
- ret = steam_sensors_register(steam);
- if (ret != 0)
- goto steam_register_sensors_fail;
- }
-
- if (do_add) {
- mutex_lock(&steam_devices_lock);
- if (list_empty(&steam->list))
- list_add(&steam->list, &steam_devices);
- mutex_unlock(&steam_devices_lock);
- }
+ steam->registered = true;
+ mutex_lock(&steam_devices_lock);
+ if (list_empty(&steam->list))
+ list_add(&steam->list, &steam_devices);
+ mutex_unlock(&steam_devices_lock);
return 0;
steam_register_sensors_fail:
steam_input_unregister(steam);
steam_register_input_fail:
+ steam_battery_unregister(steam);
+ cancel_work_sync(&steam->rumble_work);
+ cancel_delayed_work_sync(&steam->mode_switch);
return ret;
}
static void steam_unregister(struct steam_device *steam)
{
- if (!steam->serial_no[0])
+ if (!steam->registered)
return;
hid_info(steam->hdev, "Steam Controller '%s' disconnected",
steam->serial_no);
+ steam->registered = false;
steam_battery_unregister(steam);
steam_sensors_unregister(steam);
steam_input_unregister(steam);
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [STABLE v6.6 5/5] HID: steam: Clean up locking
2026-10-13 9:11 [STABLE v6.6 1/5] HID: hid-steam: Make client_opened a counter Lee Jones
` (2 preceding siblings ...)
2026-10-13 9:11 ` [STABLE v6.6 4/5] HID: steam: Refactor registration Lee Jones
@ 2026-10-13 9:11 ` Lee Jones
3 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-10-13 9:11 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
Cc: stable, Vicki Pfau, Jiri Kosina
From: Vicki Pfau <vi@endrift.com>
[ Upstream commit de1d341b9b3ec9655f31fb8b44f784cca5e670ad ]
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>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Drop report_mutex from steam_get_serial() instead of
steam_exchange_report_id(), preserve lizard_mode check order in
steam_mode_switch_cb(), and omit sensor open/close,
coalesce_rumble_work and Ibex changes as a0fbd9437d7d, 1d4549fd1115,
fcfa7db89f7a and 0a80b4e8ec6a are not present]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/hid-steam.c | 92 ++++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 43 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index 06c2fcd134ce..61e8070bed3f 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -294,6 +294,7 @@ struct steam_device {
spinlock_t lock;
struct hid_device *hdev, *client_hdev;
struct mutex report_mutex;
+ struct mutex registration_mutex;
unsigned long client_opened;
struct input_dev __rcu *input;
struct input_dev __rcu *sensors;
@@ -446,21 +447,16 @@ static int steam_get_serial(struct steam_device *steam)
u8 cmd[] = {ID_GET_STRING_ATTRIBUTE, 0x15, ATTRIB_STR_UNIT_SERIAL};
u8 reply[3 + STEAM_SERIAL_LEN + 1];
- mutex_lock(&steam->report_mutex);
ret = steam_send_report(steam, cmd, sizeof(cmd));
if (ret < 0)
- goto out;
+ return ret;
ret = steam_recv_report(steam, reply, sizeof(reply));
if (ret < 0)
- goto out;
- if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] != 0x15 || reply[2] != ATTRIB_STR_UNIT_SERIAL) {
- ret = -EIO;
- goto out;
- }
+ return ret;
+ if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] != 0x15 || reply[2] != ATTRIB_STR_UNIT_SERIAL)
+ return -EIO;
reply[3 + STEAM_SERIAL_LEN] = 0;
strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no));
-out:
- mutex_unlock(&steam->report_mutex);
return ret;
}
@@ -503,9 +499,7 @@ static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad,
report[8] = count >> 8;
report[9] = gain;
- mutex_lock(&steam->report_mutex);
ret = steam_send_report(steam, report, sizeof(report));
- mutex_unlock(&steam->report_mutex);
return ret;
}
@@ -525,9 +519,7 @@ static inline int steam_haptic_rumble(struct steam_device *steam,
report[9] = left_gain;
report[10] = right_gain;
- mutex_lock(&steam->report_mutex);
ret = steam_send_report(steam, report, sizeof(report));
- mutex_unlock(&steam->report_mutex);
return ret;
}
@@ -535,8 +527,11 @@ 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);
}
#ifdef CONFIG_STEAM_FF
@@ -558,14 +553,11 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
enable = false;
if (enable) {
- mutex_lock(&steam->report_mutex);
/* enable esc, enter, cursors */
steam_send_report_byte(steam, ID_SET_DEFAULT_DIGITAL_MAPPINGS);
/* reset settings */
steam_send_report_byte(steam, ID_LOAD_DEFAULT_SETTINGS);
- mutex_unlock(&steam->report_mutex);
} else {
- mutex_lock(&steam->report_mutex);
/* disable esc, enter, cursor */
steam_send_report_byte(steam, ID_CLEAR_DIGITAL_MAPPINGS);
@@ -577,13 +569,11 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable haptic click */
SETTING_STEAM_WATCHDOG_ENABLE, 0, /* disable watchdog that tests if Steam is active */
0);
- mutex_unlock(&steam->report_mutex);
} else {
steam_write_settings(steam,
SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */
SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */
0);
- mutex_unlock(&steam->report_mutex);
}
}
}
@@ -592,7 +582,7 @@ 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
@@ -601,9 +591,10 @@ static int steam_input_open(struct input_dev *dev)
*/
if (!(steam->quirks & STEAM_QUIRK_DECK)) {
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);
}
@@ -614,13 +605,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)) {
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);
}
}
@@ -955,15 +947,19 @@ static int steam_register(struct steam_device *steam)
{
int ret;
+ mutex_lock(&steam->registration_mutex);
/*
* This function can be called several times in a row with the
* wireless adaptor, without steam_unregister() between them, because
* another client send a get_connection_status command, for example.
* The battery and serial number are set just once per device.
*/
- if (steam->registered)
+ if (steam->registered) {
+ mutex_unlock(&steam->registration_mutex);
return 0;
+ }
+ mutex_lock(&steam->report_mutex);
/*
* Unlikely, but getting the serial could fail, and it is not so
* important, so make up a serial number and go on.
@@ -975,11 +971,13 @@ static int steam_register(struct steam_device *steam)
hid_info(steam->hdev, "Steam Controller '%s' connected",
steam->serial_no);
+ steam_set_lizard_mode(steam, lizard_mode);
+ mutex_unlock(&steam->report_mutex);
+
/* ignore battery errors, we can live without it */
if (steam->quirks & STEAM_QUIRK_WIRELESS)
steam_battery_register(steam);
- steam_set_lizard_mode(steam, lizard_mode);
ret = steam_input_register(steam);
if (ret != 0)
goto steam_register_input_fail;
@@ -988,6 +986,7 @@ static int steam_register(struct steam_device *steam)
goto steam_register_sensors_fail;
steam->registered = true;
+ mutex_unlock(&steam->registration_mutex);
mutex_lock(&steam_devices_lock);
if (list_empty(&steam->list))
list_add(&steam->list, &steam_devices);
@@ -998,6 +997,7 @@ static int steam_register(struct steam_device *steam)
steam_input_unregister(steam);
steam_register_input_fail:
steam_battery_unregister(steam);
+ mutex_unlock(&steam->registration_mutex);
cancel_work_sync(&steam->rumble_work);
cancel_delayed_work_sync(&steam->mode_switch);
return ret;
@@ -1010,10 +1010,12 @@ static void steam_unregister(struct steam_device *steam)
hid_info(steam->hdev, "Steam Controller '%s' disconnected",
steam->serial_no);
+ mutex_lock(&steam->registration_mutex);
steam->registered = false;
steam_battery_unregister(steam);
steam_sensors_unregister(steam);
steam_input_unregister(steam);
+ mutex_unlock(&steam->registration_mutex);
cancel_work_sync(&steam->rumble_work);
cancel_delayed_work_sync(&steam->mode_switch);
mutex_lock(&steam_devices_lock);
@@ -1054,22 +1056,24 @@ static void steam_mode_switch_cb(struct work_struct *work)
struct steam_device, mode_switch);
unsigned long flags;
bool client_opened;
+ bool gamepad_mode;
+
+ 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);
if (!lizard_mode)
return;
- if (steam->gamepad_mode)
+ guard(mutex)(&steam->report_mutex);
+ 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);
- }
+ else 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);
@@ -1224,6 +1228,7 @@ static int steam_probe(struct hid_device *hdev,
hid_set_drvdata(hdev, steam);
spin_lock_init(&steam->lock);
mutex_init(&steam->report_mutex);
+ mutex_init(&steam->registration_mutex);
steam->quirks = id->driver_data;
INIT_WORK(&steam->work_connect, steam_work_connect_cb);
INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb);
@@ -1319,13 +1324,10 @@ static void steam_remove(struct hid_device *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",
@@ -1695,8 +1697,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];
@@ -1704,10 +1704,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->voltage = volts;
steam->battery_charge = batt;
- spin_unlock_irqrestore(&steam->lock, flags);
power_supply_changed(battery);
}
rcu_read_unlock();
@@ -1725,6 +1723,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, HID_FEATURE_REPORT,
data, size, 0);
@@ -1809,6 +1808,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)
@@ -1816,8 +1817,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.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread