From nobody Mon Sep 28 20:05:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B2F06442FDE; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; cv=none; b=S9L6CaVOQa39jUdc0iIrgYm2uLoC0NdMonpLma/RBmD95gPLRJlkoJybrTGY2gkDiK7ztoBccpfzDN4MAbHA34qy+TPSgRMYLOUEntZ1UKCxlpKfD4+ltjbWAu276LyAFCtAq0OoHZT/PVPUY4NpiBbvK9+IWiLZVfRgSHk94os= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; c=relaxed/simple; bh=+IqWwA2cdc2aw+WXnNBLXR5Jq6+YKLS5E0CzDhozjwg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Si9rQ4gjVK648mjyYHTWoBFQ2pb7pkb//4MHL9FopMpQp/nKee3AJzDRkZKh2EcMT28FJo/616Mjj7/bTFKrmw6s5Ia/e5gunVGa0So+gdN7ToxiLPgRr/CcMx1LPpz//sJJ8Kj4TP53UDwliLTh1TXkgs2NoHQJGw/iZTWTNMc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cNTHx7wi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cNTHx7wi" Received: by smtp.kernel.org (Postfix) with ESMTPS id 377E9C2BCF4; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786996450; bh=+IqWwA2cdc2aw+WXnNBLXR5Jq6+YKLS5E0CzDhozjwg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cNTHx7wijcComiQ4cxrdYDcd2+2dL7clJ2PAGnVxWWXTNZZsJLHIckkvWNpBxr4vx 67CUaa3uHxzwJUhPrzU5/hommyQFh/BJ5NjTU3ekQATp63tN9TJ2SjlUSJjUUpa6bW bDMSACw46xFGpEgBnASDijTWda/mtzC0Z0gNYA6IiYmZb6bpPld/jbtNfJAFMmRyb0 WbkfYPpAntgVKS60OEXV+qfcYMgLGFueZ76lt7B9Ff2SGajOuajUBR4hs+TU1sI3Or lDx2pgHS9bli54DGBtYEnwBLdxMRBZ5EH2irMvkEeIiG/9aigPgpjmaDpn9zD58uFk vVd3FawrGxUxA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1620EC5B572; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) From: Sven Peter Date: Mon, 17 Aug 2026 21:53:58 +0200 Subject: [PATCH 1/5] thunderbolt: Fix tunnel reference leak when the DPRX work is not started Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260817-b4-tbt-fixes-v1-1-eded2461f5fc@kernel.org> References: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> In-Reply-To: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio , Sven Peter , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1721; i=sven@kernel.org; h=from:subject:message-id; bh=+IqWwA2cdc2aw+WXnNBLXR5Jq6+YKLS5E0CzDhozjwg=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1Zz2u1wKb3JO2af3PTArFq3ZMFVjujVmVtjf1a2HPQrc P/eueZVRykLgxgXg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAiAtwMfzg/T9r5J1kpgNep dsOEUoWejAUvK7aa/P+8xGTv4xyVnXMZ/qez/xZ/ebLIMEf8nKiaqs4a9VtXjjk9rfE59mXPOa5 TcmwA X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 tb_dp_dprx_start always takes a tunnel reference which is only dropped by dprx_work eventually. Tunnels that have no callback don't ever queue that work and tb_dp_dprx_stop then has nothing to cancel. It however only releases the reference if cancel_delayed_work returned true and the reference is leaked then. Fix this by only taking the reference when dprx_work is actually queued. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- I didn't actually hit this on hardware but found it while fixing a domain leak in the same area and that fix depends on this one. --- drivers/thunderbolt/tunnel.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index b7f32305f14a..50580ebdac4b 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1113,15 +1113,14 @@ static void tb_dp_dprx_work(struct work_struct *wor= k) =20 static int tb_dp_dprx_start(struct tb_tunnel *tunnel) { - /* - * Bump up the reference to keep the tunnel around. It will be - * dropped in tb_dp_dprx_stop() once the tunnel is deactivated. - */ - tb_tunnel_get(tunnel); - - tunnel->dprx_started =3D true; - if (tunnel->callback) { + /* + * Bump up the reference to keep the tunnel around until the + * work has run or has been canceled. + */ + tb_tunnel_get(tunnel); + + tunnel->dprx_started =3D true; tunnel->dprx_timeout =3D dprx_timeout_to_ktime(dprx_timeout); queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0); return -EINPROGRESS; --=20 2.55.0 From nobody Mon Sep 28 20:05:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B2E49442FD6; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; cv=none; b=TUR38EbitMvpvj1EIjViYRWOSSq8lupjy3NBV1+rko40sU6hCoaVt66KtlBqGDNS3w5qvcAGryQ83CWvpZpAqi2pvHyKoF7nfVdXr8mwW1SBHnJAoQLL/CQhJHi8zoPsV+gIF8VOrat3NDTb+jU+j3SBbKU+ZLz67gAM9vGiv+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; c=relaxed/simple; bh=uuxuwqQ2kuaFD3by4pKZjHi6sqSY36ifjKngOd509eo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eecx0rqJ6/vh+gExmjceVJWea++TU5B3zeot9NeU4ClgFnSyRFOQtJTkiJb/U4mrPaCeTNDG5+OZOJqZMzMlXHGKOysZjsvo3DsRyeGSTpg7jYmj3MBIW2AJ/vwrWmpTH5F1jyh4IqiyvOUbLkKR9ZqT96t756gGBxDRinCjA94= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j7LjNLaS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j7LjNLaS" Received: by smtp.kernel.org (Postfix) with ESMTPS id 48577C2BCFA; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786996450; bh=uuxuwqQ2kuaFD3by4pKZjHi6sqSY36ifjKngOd509eo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=j7LjNLaSRVCKTuwziC5/jPsrG/h298FwIAztSkVD2ehjbESPt+Zg+/Jn/7CVmstBA 8xIN9WRoR4LFx8WryB4Tll7WL1ci54qSbLGR8GxSQLCoX1WN0ZkDTTucyQUlcltWL6 nAswlGEOdLsJElMd0F6llDFHhl2ZDE4w7K7I6749LeKMK0rgoMM6g8ZcjdstCD/AB0 DnqY7A4tDLBhsAEL4fpmsre7LEF4aLw0S5wpiW1xNsYcPJi3bu0wlGEBjWes0VsYt1 gkW2mSmCiaAyOPYCZQ/c2njvz4I8ldrqFl9X2XmacO4UL0VhqZ0nWvnM4YY3sQF6sO 1wm7+YfZDi9MA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26BE5C5DF7A; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) From: Sven Peter Date: Mon, 17 Aug 2026 21:53:59 +0200 Subject: [PATCH 2/5] thunderbolt: Hold a switch reference for each path hop Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260817-b4-tbt-fixes-v1-2-eded2461f5fc@kernel.org> References: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> In-Reply-To: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio , Sven Peter , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3630; i=sven@kernel.org; h=from:subject:message-id; bh=uuxuwqQ2kuaFD3by4pKZjHi6sqSY36ifjKngOd509eo=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1Zz2p0t7mUen/f9Klz3eIbtHdGL4XP9vCS1n+wpX60ny dBf9HtfRykLgxgXg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAib/oY/mcK31WfeVle4ZVj 8vqmc2Xb6mIunXnePVHxg8F65gLjO78Y/tfYxBxaGx14iu1ueY5YqL/3z6jamdfa4wSt95pdn7H 0MCcA X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 tb_stop drops the reference to all DP tunnels but does not deactivate them, thus nothing cancels a dprx_work still in flight (which holds its own tunnel reference) and the tunnel can outlive tb_switch_remove. The HopID releases in tb_path_free then operate on freed IDAs and trigger warnings like ida_free called for id=3D8 which is not allocated. Take or release a reference for both ports of each hop whenever the HopIDs are allocated or released to ensure they have the same lifetime. The KUnit tests allocate their switches without ever registering them so initialize the embedded struct device there as well to make these references work. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/path.c | 21 +++++++++++++++++++++ drivers/thunderbolt/test.c | 12 ++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c index b2c322e76b8a..02c5e7a2101e 100644 --- a/drivers/thunderbolt/path.c +++ b/drivers/thunderbolt/path.c @@ -196,6 +196,12 @@ struct tb_path *tb_path_discover(struct tb_port *src, = int src_hopid, path->hops[i].out_port =3D out_port; path->hops[i].next_hop_index =3D next_hop; =20 + /* Keep the ports alive, see tb_path_free() */ + if (alloc_hopid) { + tb_switch_get(path->hops[i].in_port->sw); + tb_switch_get(path->hops[i].out_port->sw); + } + tb_dump_hop(&path->hops[i], &hop); =20 h =3D next_hop; @@ -323,6 +329,10 @@ struct tb_path *tb_path_alloc(struct tb *tb, struct tb= _port *src, int src_hopid, path->hops[i].out_port =3D out_port; path->hops[i].next_hop_index =3D out_hopid; =20 + /* Keep the ports alive, see tb_path_free() */ + tb_switch_get(path->hops[i].in_port->sw); + tb_switch_get(path->hops[i].out_port->sw); + in_hopid =3D out_hopid; } =20 @@ -356,6 +366,17 @@ void tb_path_free(struct tb_path *path) if (hop->out_port) tb_port_release_out_hopid(hop->out_port, hop->next_hop_index); + /* + * Only drop the switch references after both HopIDs + * have been released: the path may be freed after the + * switch was already removed (e.g. asynchronous DP + * tunnel teardown) and these references are what + * keeps the ports and their HopID IDAs alive. + */ + if (hop->in_port) + tb_switch_put(hop->in_port->sw); + if (hop->out_port) + tb_switch_put(hop->out_port->sw); } } =20 diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 05652ee82fbf..034c56845380 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -33,6 +33,11 @@ static void kunit_ida_init(struct kunit *test, struct id= a *ida) kunit_alloc_resource(test, __ida_init, __ida_destroy, GFP_KERNEL, ida); } =20 +static void tb_test_switch_release(struct device *dev) +{ + /* The memory is owned by KUnit, nothing to do here */ +} + static struct tb_switch *alloc_switch(struct kunit *test, u64 route, u8 upstream_port, u8 max_port_number) { @@ -44,6 +49,13 @@ static struct tb_switch *alloc_switch(struct kunit *test= , u64 route, if (!sw) return NULL; =20 + /* + * The paths take a reference to their switches and those devices + * have to be initialized for that to work. + */ + sw->dev.release =3D tb_test_switch_release; + device_initialize(&sw->dev); + sw->config.upstream_port_number =3D upstream_port; sw->config.depth =3D tb_route_length(route); sw->config.route_hi =3D upper_32_bits(route); --=20 2.55.0 From nobody Mon Sep 28 20:05:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B732D448384; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; cv=none; b=mQsomU5rlOv8l7xN7g5CVc47hBXFUF+vPwHhhRBbU8RJen66HIVPWq0UfDuSonIHtSXrSDVqS8nOUUaZjYPc/pLyuh1ARcrDmNS1MTJT1zXSA+rZnpBBisIQ/SnJZMExqIQpS465YzlEOiW3HwxfXxOW1x5EKVKdFe7jlzIzmGI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; c=relaxed/simple; bh=zjk4QT3VNOWscQLSaRMfjv/7SUgD1nm1RUMMr8V4Hf8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Va2aG0JlU/A0AcIcqRabkY96avibeTv3XTYoHFD09ahDl/oWdsL7zIxvL2VNv0usUigbg2/cqhNyW6aQCRBmu1y40SR2f1mDib5ikt/XM0FcrcSj6S+SffnO+YDV6kFuVSp9g8ESFxjyd1kadF54BeerwyLce6/8qsZZrWWrE4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gepoyQWO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gepoyQWO" Received: by smtp.kernel.org (Postfix) with ESMTPS id 54783C2BCFB; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786996450; bh=zjk4QT3VNOWscQLSaRMfjv/7SUgD1nm1RUMMr8V4Hf8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gepoyQWO84Kfi+fyrKOT+jq4GMW6T86vHTiCh24NGPBuMb6N0HNqh6DhyDM8si7he v/r0w7M4ulC0/0+wB++IIZet8vgoerWWqSJ4HOY4lu8pkujjB/LenOY+6j8UP+VhlB zOceutO09YofeB7dxPKxOUOPdp976Lr22BXW5Sh2vgiiAFuERkUHMXU5f/9E6eLC+P eCkifBdZpxUEUFiyyu3il9pnQykUVCS8KmCCCyCMZzAuvy91xI2220uk1DvxmW2Ppl wksh7K2eL8VFeslEdIDq2lTI1iwzMMXam8hesIM8T66YLeUvk7wn4mmmG0lXYKFsVI 6R5AYmTU6elFQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 374C0C5DF7D; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) From: Sven Peter Date: Mon, 17 Aug 2026 21:54:00 +0200 Subject: [PATCH 3/5] thunderbolt: Fix domain reference leak when DPRX read is canceled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260817-b4-tbt-fixes-v1-3-eded2461f5fc@kernel.org> References: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> In-Reply-To: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio , Sven Peter , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3515; i=sven@kernel.org; h=from:subject:message-id; bh=zjk4QT3VNOWscQLSaRMfjv/7SUgD1nm1RUMMr8V4Hf8=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1Zz2l2GHUW8VzdH1G3el8+Td29KjMzFzOZdRhkiHZPLP 5/jXt3eUcrCIMbFICumyLJ9v73pk4dvBJduuvQeZg4rE9gQLk4BmMi+lwz/ffmOXfo8Y+63Nas/ HlJI45xu2VSvnKnLq3DnnHWDH9/U34wMryYXFXL1rvQ8zTcxgydL8MfGxY0S/LcqBM6/TXS2Lt7 GCQA= X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 tb_tunnel_one_dp takes a domain reference which is only dropped once tb_dp_tunnel_active has run on the work queue. If that work is cancelled that reference is leaked. Since commit f5cc545f5969 ("thunderbolt: Wait for tb_domain_release() to complete when driver is removed") instead of just leaking memory this now also blocks in the completion wait forever when unbinding the driver. That reference only exists to keep the domain around while the DPRX work is scheduled so let the work itself own it: take it in tb_dp_dprx_start and drop it in both places that end the work. Get/put are then paired inside the same file and it doesn't matter anymore if the callback ever runs. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/tb.c | 6 +----- drivers/thunderbolt/tunnel.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index f43f2d952372..fb9da53fe391 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1964,8 +1964,6 @@ static void tb_dp_tunnel_active(struct tb_tunnel *tun= nel, void *data) tb_dp_resource_unavailable(tb, in, "DPRX negotiation failed"); } mutex_unlock(&tb->lock); - - tb_domain_put(tb); } =20 static void tb_tunnel_one_dp(struct tb *tb, struct tb_port *in, @@ -2026,8 +2024,7 @@ static void tb_tunnel_one_dp(struct tb *tb, struct tb= _port *in, available_up, available_down); =20 tunnel =3D tb_tunnel_alloc_dp(tb, in, out, link_nr, available_up, - available_down, tb_dp_tunnel_active, - tb_domain_get(tb)); + available_down, tb_dp_tunnel_active, tb); if (!tunnel) { tb_port_dbg(out, "could not allocate DP tunnel\n"); goto err_reclaim_usb; @@ -2048,7 +2045,6 @@ static void tb_tunnel_one_dp(struct tb *tb, struct tb= _port *in, tb_tunnel_put(tunnel); err_reclaim_usb: tb_reclaim_usb3_bandwidth(tb, in, out); - tb_domain_put(tb); err_detach_group: tb_detach_bandwidth_group(in); err_dealloc_dp: diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 50580ebdac4b..82d9c0b556dd 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1109,16 +1109,18 @@ static void tb_dp_dprx_work(struct work_struct *wor= k) if (tunnel->callback) tunnel->callback(tunnel, tunnel->callback_data); tb_tunnel_put(tunnel); + tb_domain_put(tb); } =20 static int tb_dp_dprx_start(struct tb_tunnel *tunnel) { if (tunnel->callback) { /* - * Bump up the reference to keep the tunnel around until the - * work has run or has been canceled. + * Bump up the references to keep the tunnel and the domain + * around until the work has run or has been canceled. */ tb_tunnel_get(tunnel); + tb_domain_get(tunnel->tb); =20 tunnel->dprx_started =3D true; tunnel->dprx_timeout =3D dprx_timeout_to_ktime(dprx_timeout); @@ -1132,11 +1134,15 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunne= l) =20 static void tb_dp_dprx_stop(struct tb_tunnel *tunnel) { + struct tb *tb =3D tunnel->tb; + if (tunnel->dprx_started) { tunnel->dprx_started =3D false; tunnel->dprx_canceled =3D true; - if (cancel_delayed_work(&tunnel->dprx_work)) + if (cancel_delayed_work(&tunnel->dprx_work)) { tb_tunnel_put(tunnel); + tb_domain_put(tb); + } } } =20 --=20 2.55.0 From nobody Mon Sep 28 20:05:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B2CD83CBE6D; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; cv=none; b=TrLrtG7/fLNOUjKO0QzyL7LlLKJ8sguG8mfNw34ZW6/NyXGubr7xnpqxcieDxN1vk7SLo6uykc0uWIy2P8VnTzCLrRFRAHiKnJsDWI4IeybeOY5NckNXYN1XjLW/tPqdRNBpnPkOBsnqPuAXQk7sS2si17fgS84lDoiD9eaoikQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996450; c=relaxed/simple; bh=Wvk/GoG5BUNG7j62FvnpVbC2KSxj9mBYK7LX+M98XUw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HAUYTk/z+ORQIejskrxUzb0DhVJBH/24KAYNJKvbaf+bGPzxuuFLFLs2FeTH9FKi4n4dbAYSUOhbEi9Rtf4O5MTv6FQyUgC7zAhSIXaCbEw92camP2DyvpIVAxlI0hoGtAqb8tqgYZc/2ozmQyF5CIRBa0uezzzCJKoS8rECnEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GJ/H/Fs6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GJ/H/Fs6" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5D3DDC2BCFC; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786996450; bh=Wvk/GoG5BUNG7j62FvnpVbC2KSxj9mBYK7LX+M98XUw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=GJ/H/Fs6QggOUmmy34BTXEShCg8Aw5WBF/rfLsuAa2ho21zussWee38eG/YO9+Lto PHj/JDj42kGnr01kVGBppRHdS4UtzEcVQaOJPZouwo+wlTyJhAcg+G6O2lYviZ0jWn UTC0xVEQ6B0fGdL1604bNslwTg13OOBom6Z2ksCCeGzx5yYBeQZOaWRMLebrkTzbsA HkjExn70iR6tEUtWJU4eR16IT60DcyACWYkh67Z/7VNK3fOuQlIr053RP2+9yJN7AC du8yfNlvoMEpkaxpzvQMocv52veTYeET4+RtgPKrRW0/x61C3doLFrMyJ8XoLsHkVL Oz3hOjjXpyq8A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47445C5DF7F; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) From: Sven Peter Date: Mon, 17 Aug 2026 21:54:01 +0200 Subject: [PATCH 4/5] thunderbolt: Don't access a DP tunnel after its DPRX read was canceled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260817-b4-tbt-fixes-v1-4-eded2461f5fc@kernel.org> References: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> In-Reply-To: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio , Sven Peter , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3140; i=sven@kernel.org; h=from:subject:message-id; bh=Wvk/GoG5BUNG7j62FvnpVbC2KSxj9mBYK7LX+M98XUw=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1Zz2j3RWz+WHPqf/6gjIbvVb2nfokfamiHuEz9eZrsZv eNjavTZjlIWBjEuBlkxRZbt++1Nnzx8I7h006X3MHNYmUCGMHBxCsBEwr4yMjzta3nyKXDTgU3l m9vftK2Li+gyK79/VWZlmuaxjc4nN+9nZJgoVvZEoOTMUq5m70MH7T4sXPRF0/bYvJ1/Us24BDq l73ADAA== X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 tb_dp_dprx_work checks dprx_canceled before it takes tb->lock so it misses a tb_dp_dprx_stop that could not cancel the already running work. It then polls the DPRX capabilities and runs the callback for a tunnel that is being torn down and touches routers that may already be gone after an unplug. Check the flag with tb->lock held instead and check it again in tb_dp_tunnel_active because the callback runs after the lock has been dropped again. Also clear the flag in tb_dp_dprx_start so that it only ever describes the work that is currently in flight. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/tb.c | 12 ++++++++++++ drivers/thunderbolt/tunnel.c | 11 +++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index fb9da53fe391..e368a6b53f64 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1910,6 +1910,18 @@ static void tb_dp_tunnel_active(struct tb_tunnel *tu= nnel, void *data) struct tb *tb =3D data; =20 mutex_lock(&tb->lock); + + /* + * If the DPRX read was canceled the tunnel is already being torn + * down by whoever canceled it. Do not touch the adapters here + * because the routers may be gone by now. + */ + if (tunnel->dprx_canceled) { + tb_tunnel_dbg(tunnel, "DPRX read canceled, not activating\n"); + mutex_unlock(&tb->lock); + return; + } + if (tb_tunnel_is_active(tunnel)) { int consumed_up, consumed_down, ret; =20 diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 82d9c0b556dd..52fa90786ff8 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1090,8 +1090,14 @@ static void tb_dp_dprx_work(struct work_struct *work) struct tb_tunnel *tunnel =3D container_of(work, typeof(*tunnel), dprx_wor= k.work); struct tb *tb =3D tunnel->tb; =20 + /* + * The DPRX read can be canceled while this work is waiting for + * tb->lock. Check the flag only once it is held: while the lock is + * held the tunnel cannot be torn down under us and the adapters are + * safe to access. + */ + mutex_lock(&tb->lock); if (!tunnel->dprx_canceled) { - mutex_lock(&tb->lock); if (tb_dp_is_usb4(tunnel->src_port->sw) && tb_dp_wait_dprx(tunnel, TB_DPRX_WAIT_TIMEOUT)) { if (ktime_before(ktime_get(), tunnel->dprx_timeout)) { @@ -1103,8 +1109,8 @@ static void tb_dp_dprx_work(struct work_struct *work) } else { tb_tunnel_set_active(tunnel, true); } - mutex_unlock(&tb->lock); } + mutex_unlock(&tb->lock); =20 if (tunnel->callback) tunnel->callback(tunnel, tunnel->callback_data); @@ -1123,6 +1129,7 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunnel) tb_domain_get(tunnel->tb); =20 tunnel->dprx_started =3D true; + tunnel->dprx_canceled =3D false; tunnel->dprx_timeout =3D dprx_timeout_to_ktime(dprx_timeout); queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0); return -EINPROGRESS; --=20 2.55.0 From nobody Mon Sep 28 20:05:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E3C1246D0B5; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996451; cv=none; b=shzehI0+5VY4e6qePvjxS5afd4mRyxBGXp3QbNw2byM6ZDDs5w8lRkWnv5DF1HG1virs9jShXjouRIiTP4SXFdcmQfJ+0Ege07ucaQwPYtkFtNTDLqMxhyJNQ+GyoDEELBo033ixwhVcrZJIICflI78f+wvEYz80HZvf74gCrFI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786996451; c=relaxed/simple; bh=xAAxDyvnDi8yNJ6ByWgjRWlh3/HZjKsKtAZ8OmkRJfM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kdevGyBMtutsxd/n9N+KgZuubQgtCDWpvpITpVoZ0TsyG8jZ7CWk6JgDJuZqZtwUAS+25nBYADUdu0VMycTfKb/M9KJRbYKeqHkmjU5rb7zj/YomCFJCW/FWRL1c32CZ99LAekA/0aR3qs2y/g453a0cyf+TH27yr0yn0moA9NM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QIEtRiu3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QIEtRiu3" Received: by smtp.kernel.org (Postfix) with ESMTPS id 714F3C4AF09; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786996450; bh=xAAxDyvnDi8yNJ6ByWgjRWlh3/HZjKsKtAZ8OmkRJfM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QIEtRiu3cyoFUP8Dlj+glac4A/3KoXETHv6QY9C08p+CnNSW0wSceq8gJ3/OrNwZN uJgmfs/nKEtc5/TrmPIrGwSLShC5MGfhOCZ50DaXcWQAyU7elkJwAxE2hwBlxT9VwV S2yPiP70Cb0UyC8ug5bqe++vRtw1bWnJFKL47yRERHbnsj2wtKYVLTzl7ZyZwmCNdW U565SMo4zJc/xCROE53PviKhBTT660Sn8oeQ2ljT+WaPDJ8mBq2wViEIOrs4XYXIYU bc72PeU8F9UEBm03Vs9qVymN/9sqg7hbIlnVLyG+V8WnYMdd6NIsgJ1Jr7dXpgITJR lfWbdW8GCiWrA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57A37C5DF7E; Mon, 17 Aug 2026 19:54:10 +0000 (UTC) From: Sven Peter Date: Mon, 17 Aug 2026 21:54:02 +0200 Subject: [PATCH 5/5] thunderbolt: Cancel the DPRX read when the domain is stopped Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260817-b4-tbt-fixes-v1-5-eded2461f5fc@kernel.org> References: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> In-Reply-To: <20260817-b4-tbt-fixes-v1-0-eded2461f5fc@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio , Sven Peter , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3116; i=sven@kernel.org; h=from:subject:message-id; bh=xAAxDyvnDi8yNJ6ByWgjRWlh3/HZjKsKtAZ8OmkRJfM=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1Zz2v3HMVJchkYPVucEcU2w2VV2NLYnJ/+X0mGDrZp95 RfXmct0lLIwiHExyIopsmzfb2/65OEbwaWbLr2HmcPKBDKEgYtTACai4sTI8Cg2d5/x75PfSv+t KXjgpv52v9D6nir1uEc1Mf3S3TuM7jP8ZDyfHekRmVYR+rytTcJ7Y9Z2z2/v+/tul5oF6nf3vO/ hAAA= X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 tb_stop only tears down DMA tunnels so a DP tunnel that is still waiting for dprx_work to complete keeps that work queued while the routers are removed and the control channel is stopped. The work only stops once the DPRX timeout has passed and because it requeues itself until then the flush_workqueue in tb_domain_remove won't wait for its final run. The callback then runs against a domain that is already torn down. A reference to that domain is kept so the completion waiting for that domain to disappear in unbind will block until the timeout is eventually reached. Just cancel the work in tb_stop. This doesn't affect DP tunnels that are already alive and keeps those displays working. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- I also didn't run into this but noticed it when fixing the hop alloc thing and think it makes sense to fix it anyway. --- drivers/thunderbolt/tb.c | 5 ++++- drivers/thunderbolt/tunnel.c | 9 +++++++++ drivers/thunderbolt/tunnel.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index e368a6b53f64..f7e68372da09 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -2958,10 +2958,13 @@ static void tb_stop(struct tb *tb) /* * DMA tunnels require the driver to be functional so we * tear them down. Other protocol tunnels can be left - * intact. + * intact but a DPRX capabilities read that is still in + * flight has to be canceled before the routers go away. */ if (tb_tunnel_is_dma(tunnel)) tb_tunnel_deactivate(tunnel); + else if (tb_tunnel_is_dp(tunnel)) + tb_tunnel_cancel_dprx(tunnel); tb_tunnel_put(tunnel); } tb_switch_remove(tb->root_switch); diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 52fa90786ff8..5b1ae5a0c12b 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -2487,6 +2487,15 @@ void tb_tunnel_deactivate(struct tb_tunnel *tunnel) tb_tunnel_set_active(tunnel, false); } =20 +/** + * tb_tunnel_cancel_dprx() - Cancel the DPRX capabilities read work + * @tunnel: tunnel to cancel the DPRX capabilities read work for + */ +void tb_tunnel_cancel_dprx(struct tb_tunnel *tunnel) +{ + tb_dp_dprx_stop(tunnel); +} + /** * tb_tunnel_port_on_path() - Does the tunnel go through port * @tunnel: Tunnel to check diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 4878763a82b3..9de5fac04269 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -138,6 +138,7 @@ struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, s= truct tb_port *up, void tb_tunnel_put(struct tb_tunnel *tunnel); int tb_tunnel_activate(struct tb_tunnel *tunnel); void tb_tunnel_deactivate(struct tb_tunnel *tunnel); +void tb_tunnel_cancel_dprx(struct tb_tunnel *tunnel); =20 /** * tb_tunnel_is_active() - Is tunnel fully activated --=20 2.55.0