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 7013F472F9B; Tue, 13 Oct 2026 09:13:02 +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=1791882784; cv=none; b=Uwd2liVyvMyJv+8OkeIvoK377bvR4oUrH4s/5QxfqtUzrQoTYVCT8ttvLM09/KX0AoTybIsX/UiZxn0TRxpNIVyi1ulv5pBTP1Ve0BWJChaI1HOpWzmp7oqSL3df9glNu10V53s2OGfZ1FDH5Db67djm3uUXjpNm3vrcNxNfSRE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791882784; c=relaxed/simple; bh=Rlaaj32c4q+IQzjqStLsCF0+kxSlxn087A9NmRe24GY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NI7Z1ewrNES07gLP3zLGhan7GRNYMb1yIwDImcLuQm305NRHtbkybg5JhWilMv0SfrW1fMt4gQqhmn2RhtYZzsRP9ar6SUz3b98vh9MGj0kNhC1BUqueXtWZDPD4AiHA4h3nRMjDSzcRenSyV4toxY7Tg32Scp4ykH59krGUAS4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WEKgegrK; 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="WEKgegrK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E14811F0089B; Tue, 13 Oct 2026 09:13:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1791882782; bh=gaAEBv0k6J+QMI0lIXjkKfM+Q2HVxPsWs9aln6118g8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WEKgegrKYiNG26PdgBz4lSeOXvULNQPAlsRvWr7Eg3csxZiiAUC1MCaiDo/zHOzwm tZg7DAq/Y9kbL0kohFgufvdTkbt/aYn9A2/74WVP/SC3cSCJhJ609FSFKgL9D0bjOZ jwF4QKmk8xog2IWQRgEajM2DP+HpFCUI/jQeVOm1PCEanqbxlVpuhQYeAnelk5iyFg 5UiPoXEpEPQNTtTQ9xJNFe6z8mC5SvP+XfwAAN7NXNU0asAZhQis8BHd6P9NKvvl58 yr8o1721GqinEAYf4mtXxTXJEDDjIJeOzw7FSsHxiMmyXXoS//P8ZqSJYoYzQ/sUm6 3HASomhGrNdOA== 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 v5.15-v5.10 6/6] HID: steam: Clean up locking Date: Tue, 13 Oct 2026 09:12:13 +0000 Message-ID: <20261013091215.529531-6-lee@kernel.org> X-Mailer: git-send-email 2.56.0.385.gd3acb90ef8-goog In-Reply-To: <20261013091215.529531-1-lee@kernel.org> References: <20261013091215.529531-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: 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 --- 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 544d45f3fc6b..4ba922d750df 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.56.0.385.gd3acb90ef8-goog