From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B56224908B2; Tue, 13 Oct 2026 09:13:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791882785; cv=none; b=OpIFhfn7Gg8ZhA+F6qK1t0C062niLnMSr2JuUlEZB02lsp4/kvwPvNaydXLDHv4FX2fdW4hNPCbXy/Vly4b8aQM3BOr7wexPY7XHuIVjNHWuqH82SQVfFTvbjaLXldpuP9Xadg/khYJCFXeYMzFjn6BMKktTEwWWcvAott7jpv0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791882785; c=relaxed/simple; bh=JaoV95Ls6c5Dxw9M12b8xV79tsA3XmDO632worOibiU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fh8HesBcDDcEikzkldILVdDLED7Gcie1e/ipWmTRwzqMbRYkBrjTZIDvsvlyQw2iXz7+PBaiRXdWuK+uUsV8aujbXZRcH/CjAwhK3pS10ipJwZm2lrxOpy9/uCS7C6Ggu1699DrGuSahaG67+7FPBermn4pJ3b+Sd9UrRev17Bk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JnHowGhV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JnHowGhV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CD2A1F00898; Tue, 13 Oct 2026 09:12:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1791882780; bh=T8njoKiw74NOo2HycKeJ1o+njVKhOn3Rn65hLB43klk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JnHowGhVCIhSk1ST0j234rFDQqgEMjgdccIse60r3n2dmCQqkYsq74WlPnSe3J0W8 oHLfZqiFRe0ABHEb++xtjwNjQdZlHzDu/iqanYcdfgF58XH4lrykL5NaGMi4VrUSqB kDr8Ul4IcAms3+qDaaUD5flS28gpK3r4OhKzFeG73csWKrZKWCCMt6R5zdUBYwle/Y 3Hw9iZLybKliO/9vhshKT6XOuaOCkKignhiXKPhIhn0tN2apJ2xxv2eSJDGFOOC0gf QJCF2Juqv7DXnA93fMdl0MDIP/92Bq9aOlpfWiwH65Reo4ZLyrLHwmjgcAUR4969dU yIM4jMnEXWjfQ== From: Lee Jones To: lee@kernel.org, Jiri Kosina , Benjamin Tissoires , Vicki Pfau , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org, Jiri Kosina Subject: [STABLE v6.1 6/6] HID: steam: Clean up locking Date: Tue, 13 Oct 2026 09:12:02 +0000 Message-ID: <20261013091204.529049-6-lee@kernel.org> X-Mailer: git-send-email 2.56.0.385.gd3acb90ef8-goog In-Reply-To: <20261013091204.529049-1-lee@kernel.org> References: <20261013091204.529049-1-lee@kernel.org> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Vicki Pfau [ 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 Signed-off-by: Jiri Kosina [Lee: Adapt to steam->mutex and omit Steam Deck sensors, mode_switch, rumble_work, coalesce_rumble_work and Ibex changes as 691ead124a0c, e133dc99fc07, a0fbd9437d7d, 1d4549fd1115, fcfa7db89f7a and 0a80b4e8ec6a are not present] Signed-off-by: Lee Jones --- drivers/hid/hid-steam.c | 59 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index aa001a293a36..bbc150167a7f 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -114,6 +114,7 @@ struct steam_device { spinlock_t lock; struct hid_device *hdev, *client_hdev; struct mutex mutex; + struct mutex registration_mutex; unsigned long client_opened; struct input_dev __rcu *input; unsigned long quirks; @@ -294,22 +295,30 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) static int steam_input_open(struct input_dev *dev) { struct steam_device *steam = input_get_drvdata(dev); + unsigned long flags; + bool client_opened; - mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + spin_lock_irqsave(&steam->lock, flags); + client_opened = steam->client_opened; + spin_unlock_irqrestore(&steam->lock, flags); + guard(mutex)(&steam->mutex); + if (!client_opened && lizard_mode) steam_set_lizard_mode(steam, false); - mutex_unlock(&steam->mutex); return 0; } static void steam_input_close(struct input_dev *dev) { struct steam_device *steam = input_get_drvdata(dev); + unsigned long flags; + bool client_opened; - mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + spin_lock_irqsave(&steam->lock, flags); + client_opened = steam->client_opened; + spin_unlock_irqrestore(&steam->lock, flags); + guard(mutex)(&steam->mutex); + if (!client_opened && lizard_mode) steam_set_lizard_mode(steam, true); - mutex_unlock(&steam->mutex); } static enum power_supply_property steam_battery_props[] = { @@ -513,40 +522,43 @@ 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->mutex); /* * Unlikely, but getting the serial could fail, and it is not so * important, so make up a serial number and go on. */ - mutex_lock(&steam->mutex); if (steam_get_serial(steam) < 0 || !steam->serial_no[0]) strscpy(steam->serial_no, "XXXXXXXXXX", sizeof(steam->serial_no)); - mutex_unlock(&steam->mutex); hid_info(steam->hdev, "Steam Controller '%s' connected", steam->serial_no); + steam_set_lizard_mode(steam, lizard_mode); + mutex_unlock(&steam->mutex); + /* ignore battery errors, we can live without it */ if (steam->quirks & STEAM_QUIRK_WIRELESS) steam_battery_register(steam); - mutex_lock(&steam->mutex); - steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); ret = steam_input_register(steam); if (ret != 0) goto steam_register_input_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); @@ -555,6 +567,7 @@ static int steam_register(struct steam_device *steam) steam_register_input_fail: steam_battery_unregister(steam); + mutex_unlock(&steam->registration_mutex); return ret; } @@ -565,9 +578,11 @@ 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_input_unregister(steam); + mutex_unlock(&steam->registration_mutex); mutex_lock(&steam_devices_lock); list_del_init(&steam->list); mutex_unlock(&steam_devices_lock); @@ -745,6 +760,7 @@ static int steam_probe(struct hid_device *hdev, hid_set_drvdata(hdev, steam); spin_lock_init(&steam->lock); mutex_init(&steam->mutex); + mutex_init(&steam->registration_mutex); steam->quirks = id->driver_data; INIT_WORK(&steam->work_connect, steam_work_connect_cb); INIT_LIST_HEAD(&steam->list); @@ -835,13 +851,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", @@ -1008,8 +1021,6 @@ static void steam_do_input_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]; @@ -1017,10 +1028,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(); @@ -1037,6 +1046,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); @@ -1108,6 +1118,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) @@ -1115,10 +1127,13 @@ static int steam_param_set_lizard_mode(const char *val, mutex_lock(&steam_devices_lock); list_for_each_entry(steam, &steam_devices, list) { - mutex_lock(&steam->mutex); - 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->mutex); steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); + } } mutex_unlock(&steam_devices_lock); return 0; -- 2.56.0.385.gd3acb90ef8-goog