From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793211564; b=5bK4BZIgEWQWTanjyvfWcV7Ucsx9Ac5J2PA9nFP1TqGC4gyCns9tngdlmCC40WzDfcii czcTdZs0X78rUkyb/2lKCoyXf3O0X49ROpVIw8ZXC1uOVu6Z9k0kIBBgQchZvpe11VIBK BvijicirV1++y057/7/gexoRGc0HwxK36TNj6mYJe/v6ZKzPpaRIGRROt5+g1csDnwrWd zYW2lnhuo21OeCZqKQ38buvxZlnGP5mdh2BhYMZQgr5G6adU0ljCzOa2UQYU0zAlUuE2a niTTwHgR5UBxEiyV2Jr8WRyF8bSalguuAhKZD+8lBb4Pdio8xkFV8VWCmOKMk2MhQ/A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793211564; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=cmR0FZOJQu4UxAN7t2A0BepiW/D3ylwVf1jqRnjWkC4=; b=aKLxRCjaAvogRnb6jP3DOq/rwSgj+r7vuKpC9EVw1GlXP1lTKMLwM/jLtRxgiHcXVbUs 6Lxkw9H5RQQkfFlXYEvkZhFI5yf+CuaclFCSb3kEpWOpOau9R51FpisPMuGttcXlatR0g RAQi06RSJ7O1b0JDUCct4H2rrkeQ3RfVJOmgY2XiZsElJHoL/6WYpro5fSeQ7br4W9qGC DHicm3Q45uqlQbCaQQaoxPPcm++hQr1CN3+lD8KS9906xnUmJHI+P6V7ZF3RUxydlZWS3 44RBIszmZGNYXyXeGNpmvyN3LYqAz2HM8ew8+w8QbzQO8NOocRdZ8YS0dMSdUgSIvuw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=okeYq1H4; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7443A606A31D; Wed, 28 Oct 2026 18:19:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=okeYq1H4 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C67EA1F01825; Wed, 28 Oct 2026 18:19:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1793211564; bh=cmR0FZOJQu4UxAN7t2A0BepiW/D3ylwVf1jqRnjWkC4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=okeYq1H46Ahx9GImckjPMYS4PKndgLKliIPCBzngBZPMmv033iwItrGjLVpcI5ocs TbB8UVIkLIEaZCZ/YFSl40jZk5BzxOcebxPuZUOitnjF/lRebxImWIAWdJGQhsQ37t PHID+whc/z3iN9N9OrW+e8KJXHhkRo1Bq2psvCM4= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Vicki Pfau , Jiri Kosina , Lee Jones , Sasha Levin Subject: [PATCH 5.15 423/571] HID: steam: Clean up locking Date: Wed, 28 Oct 2026 17:59:30 +0100 Message-ID: <20261028170018.053120251@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261028170008.009143722@linuxfoundation.org> References: <20261028170008.009143722@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 5.15-stable review patch. If anyone has any objections, please let me know. ------------------ 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: Use explicit lock/unlock calls instead of guard(), 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 Signed-off-by: Sasha Levin --- drivers/hid/hid-steam.c | 61 +++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 544d45f3fc6b5..4ba922d750df3 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,9 +295,14 @@ 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; + spin_lock_irqsave(&steam->lock, flags); + client_opened = steam->client_opened; + spin_unlock_irqrestore(&steam->lock, flags); mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + if (!client_opened && lizard_mode) steam_set_lizard_mode(steam, false); mutex_unlock(&steam->mutex); return 0; @@ -305,9 +311,14 @@ static int steam_input_open(struct input_dev *dev) static void steam_input_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); mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + if (!client_opened && lizard_mode) steam_set_lizard_mode(steam, true); mutex_unlock(&steam->mutex); } @@ -513,40 +524,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]) strlcpy(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 +569,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 +580,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 +762,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 +853,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 +1023,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 +1030,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(); @@ -1033,10 +1044,12 @@ static int steam_raw_event(struct hid_device *hdev, struct steam_device *steam = hid_get_drvdata(hdev); struct input_dev *input; struct power_supply *battery; + unsigned long flags; if (!steam) return 0; + spin_lock_irqsave(&steam->lock, flags); if (steam->client_opened) hid_input_report(steam->client_hdev, HID_FEATURE_REPORT, data, size, 0); @@ -1057,12 +1070,12 @@ static int steam_raw_event(struct hid_device *hdev, */ if (size != 64 || data[0] != 1 || data[1] != 0) - return 0; + goto out; switch (data[2]) { case STEAM_EV_INPUT_DATA: if (steam->client_opened) - return 0; + goto out; rcu_read_lock(); input = rcu_dereference(steam->input); if (likely(input)) @@ -1100,6 +1113,8 @@ static int steam_raw_event(struct hid_device *hdev, } break; } +out: + spin_unlock_irqrestore(&steam->lock, flags); return 0; } @@ -1108,6 +1123,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 +1132,14 @@ 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) { + mutex_lock(&steam->mutex); steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); + mutex_unlock(&steam->mutex); + } } mutex_unlock(&steam_devices_lock); return 0; -- 2.53.0