From nobody Mon Sep 28 09:59:44 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 8BBB331B80E; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=Qxv+Dedq1Cl1zApJL5vGHNLWBd9745ABPoksdQzaN02m+w3795DZP5grJ7nZ5KuVum25CtD+Th7Wchg0k8MraxOXYcfIkVIeqAj/xOyr7yLRpnzK03xqdVBgxiMsrwKK5d0AXIGM7ndleIAd+4Rv5Ff2WVwc3GGlYPv+Je9My7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=esh7Wy98o9M7H1i80O38p9rP0EepwdyMIe/Wn+DxPis=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lmZjtgGYnGfU/EShWTFG6iba9Y9iavQSQ6R8mNOZuRvMhMY1Qzc7ANM0Kviw+OyIt5gQhqLUKe7LYQKmHjSIBm4sMiLxf7uMVx3GGa+et4aFB7dJCu/bEuir+MoP9nJTwgvM4pr7lodgQs6gKiUyLQms4puf4b1nViBQ5pvpwHQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RdcLyvY1; 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="RdcLyvY1" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1CD57C2BCFA; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=esh7Wy98o9M7H1i80O38p9rP0EepwdyMIe/Wn+DxPis=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RdcLyvY1DTRlvKfkmgtYATIXzKjj5ISKQaGALpcurNAAck/BWJseDKkRAEl4jCI/4 w+hb+5HqGH/Pwlxh4zPU/cjqeycVnrxmLKVFGtR1FXZXSKB6VU5IHLzMD6W+oVXXa4 VVi79siJK2afptSRlHS4ZeLmRhlUfCjLahJTMDDTQUQi2spyF0+w/z8KbkSeSN/qCu xXQtFNYjvLhvReh2n48abNx8+vNuBe1nkquWJMbwW0tIBAhCHeO5AAuCFq4g+vq4M3 vai1kuitqtpbWzxaJ1UYRCDD9Q4Z8tAxaJgQ5ld5Hfsvrh+5IQuSy9ogJL0/GnguYs MhJlU1wuLMvrw== 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 EF53BC5DF97; Sun, 23 Aug 2026 16:10:14 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:14 +0200 Subject: [PATCH v2 1/7] thunderbolt: Hold a router 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: <20260823-b4-tbt-fixes-v2-1-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3958; i=sven@kernel.org; h=from:subject:message-id; bh=esh7Wy98o9M7H1i80O38p9rP0EepwdyMIe/Wn+DxPis=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dGzWuevXcjTCqnavfG+S4bxzQZjNYxdjrzpmFqvfi /SPL7jfUcrCIMbFICumyLJ9v73pk4dvBJduuvQeZg4rE8gQBi5OAZiItSsjw4JquxC9k7WOgpvM JvmeFLAtr7634LrM2Ri+fV5/8i1lPBkZLtrNq5x3ne3gm7uPqmOWGYs2HbrHsenemfs/zodI1PA HMgAA 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. This can be triggered by unbinding the driver while a DP tunnel is still waiting for the DPRX capabilities read to finish. On the Apple NHI unplugging the cable runs into just that reliably because the read can never finish right now and because the unplug powers down the entire USB4 complex and removes the NHI device. 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 09:59:44 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 8BA4729B76C; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=CePUJaeEM5MTTDqbDvN+XmlmNKICoh4YJhnQT9ix7EsdDfYG0e9wA/N91L1i5qSbh3hu5bKhKIxbl1PKEcLzCpdg07UeJLpEQOzNWPU+IsxrIYdA9eRujk3EzEcVg1NqzZbLhbBsO/FRhL37dpmYI15xMtVHpevyFEBuQtylM04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=Otks1eFhl3B/2yj7KleJv87pPAk0iPsCyon/LUQIjrQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UHilJ5aTOS01z9m8/vAGlWJK3wC3Gyi0r+KAoi2Bu1qsHrkySuCNJ6luPBwIoLGIGWWWoi+8arQghWWaJ7PQ6LsJMcYJ4kIMxkZiEUqwps6k9ZyWafa08ccAcTeV15Ruz7P+vt86OOhTufuSP3tQN2TMUENz7bPsDfUypdeGppI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l+I06Upt; 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="l+I06Upt" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3B9F0C2BCFB; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=Otks1eFhl3B/2yj7KleJv87pPAk0iPsCyon/LUQIjrQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=l+I06UptdVLqn9QVoqbuWWIdWendtlR+yaswkg5dpe0s3d0B3Q80jLTwQr2uNVeYp zxqtKOWHW30rz4+51+vKCygQpTcwVPZrR4/+bbxTHzdwa4m7Wd5wSXrcao/RM6V4P3 ji813Ru6ZAOtnOofRoN7YcYoBK1/1PN4s4o8GCpzXbQPT8mrwd5GlRllDm34P8d0q1 ld/e8BdWde9nQ2R0ifhOVOFkO2l/kxC0XGgNZilLiyGBkogezU0w6vu0wB4wlsCHSF gjn/LpfhLfIxWVgL6+SvXS2lOcyFx6jtUgwhQYWVb38BZ6EXS2MWoGDrT+uuM+LqZA eNJ7eSReAvt+A== 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 17567C5DF9A; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:15 +0200 Subject: [PATCH v2 2/7] thunderbolt: Make the DP tunnel activation callback mandatory 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: <20260823-b4-tbt-fixes-v2-2-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13359; i=sven@kernel.org; h=from:subject:message-id; bh=Otks1eFhl3B/2yj7KleJv87pPAk0iPsCyon/LUQIjrQ=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dJwq83y1bYaV/Lv8+LNY/1zmK29Mvsf+69qfrjS9D iknvfSOUhYGMS4GWTFFlu377U2fPHwjuHTTpfcwc1iZQIYwcHEKwET+T2L4n1HOw9YePG0DY7dR bpnr2VPCe+QV3+g/va58NCh7efDttQz/VA9Fv/mwbMmNRzmr1N5OVi98GXE6avPd/mQLxnjJC/r LmQE= 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_alloc_dp() takes an optional callback which is run from dprx_work once the DPRX capabilities read has completed. Without that callback tb_dp_dprx_start() reads the capabilities synchronously and never queues the work. It however always takes a tunnel reference which is only dropped by dprx_work itself or by tb_dp_dprx_stop() when cancel_delayed_work() actually canceled that work. That reference is thus leaked for every tunnel without a callback. The only tunnels without one are those from tb_tunnel_discover_dp(), which are activated again when restoring from hibernation. Pass the callback to tb_tunnel_discover_dp() as well and drop the synchronous path such that the DPRX capabilities are always read from dprx_work. Hibernation restore then also no longer blocks for up to 12 seconds while waiting for that read to complete. Also fix up the KUnit tests. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/tb.c | 4 +++- drivers/thunderbolt/test.c | 37 +++++++++++++++++++++++----------- drivers/thunderbolt/tunnel.c | 47 ++++++++++++++++++++++++----------------= ---- drivers/thunderbolt/tunnel.h | 8 +++++--- 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index f43f2d952372..29b9879c40d8 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -89,6 +89,7 @@ static void tb_dp_resource_unavailable(struct tb *tb, str= uct tb_port *port, const char *reason); static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 por= t, int retry, unsigned long delay); +static void tb_dp_tunnel_active(struct tb_tunnel *tunnel, void *data); =20 static void tb_queue_hotplug(struct tb *tb, u64 route, u8 port, bool unplu= g) { @@ -385,7 +386,8 @@ static void tb_switch_discover_tunnels(struct tb_switch= *sw, =20 switch (port->config.type) { case TB_TYPE_DP_HDMI_IN: - tunnel =3D tb_tunnel_discover_dp(tb, port, alloc_hopids); + tunnel =3D tb_tunnel_discover_dp(tb, port, alloc_hopids, + tb_dp_tunnel_active, tb); tb_increase_tmu_accuracy(tunnel); break; =20 diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 034c56845380..fc3f647bf664 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -1398,6 +1398,10 @@ static void tb_test_tunnel_pcie(struct kunit *test) tb_tunnel_put(tunnel1); } =20 +static void tb_test_dp_tunnel_active(struct tb_tunnel *tunnel, void *data) +{ +} + static void tb_test_tunnel_dp(struct kunit *test) { struct tb_switch *host, *dev; @@ -1418,7 +1422,8 @@ static void tb_test_tunnel_dp(struct kunit *test) in =3D &host->ports[5]; out =3D &dev->ports[13]; =20 - tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1464,7 +1469,8 @@ static void tb_test_tunnel_dp_chain(struct kunit *tes= t) in =3D &host->ports[5]; out =3D &dev4->ports[14]; =20 - tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1514,7 +1520,8 @@ static void tb_test_tunnel_dp_tree(struct kunit *test) in =3D &dev2->ports[13]; out =3D &dev5->ports[13]; =20 - tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1579,7 +1586,8 @@ static void tb_test_tunnel_dp_max_length(struct kunit= *test) in =3D &dev6->ports[13]; out =3D &dev12->ports[13]; =20 - tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1649,7 +1657,8 @@ static void tb_test_tunnel_3dp(struct kunit *test) out2 =3D &dev5->ports[13]; out3 =3D &dev4->ports[14]; =20 - tunnel1 =3D tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0, NULL, NULL); + tunnel1 =3D tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_TRUE(test, tunnel1 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, in1); @@ -1657,7 +1666,8 @@ static void tb_test_tunnel_3dp(struct kunit *test) KUNIT_ASSERT_EQ(test, tunnel1->npaths, 3); KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 3); =20 - tunnel2 =3D tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0, NULL, NULL); + tunnel2 =3D tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_TRUE(test, tunnel2 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, in2); @@ -1665,7 +1675,8 @@ static void tb_test_tunnel_3dp(struct kunit *test) KUNIT_ASSERT_EQ(test, tunnel2->npaths, 3); KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 4); =20 - tunnel3 =3D tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0, NULL, NULL); + tunnel3 =3D tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_TRUE(test, tunnel3 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel3->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel3->src_port, in3); @@ -1763,7 +1774,8 @@ static void tb_test_tunnel_port_on_path(struct kunit = *test) in =3D &dev2->ports[13]; out =3D &dev5->ports[13]; =20 - dp_tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + dp_tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel); =20 KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, in)); @@ -2195,7 +2207,8 @@ static void tb_test_credit_alloc_dp(struct kunit *tes= t) in =3D &host->ports[5]; out =3D &dev->ports[14]; =20 - tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)3); =20 @@ -2431,7 +2444,8 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL1(struct ku= nit *test, =20 in =3D &host->ports[5]; out =3D &dev->ports[13]; - dp_tunnel1 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + dp_tunnel1 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel1); KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3); =20 @@ -2468,7 +2482,8 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL2(struct ku= nit *test, =20 in =3D &host->ports[6]; out =3D &dev->ports[14]; - dp_tunnel2 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, NULL, NULL); + dp_tunnel2 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, + tb_test_dp_tunnel_active, NULL); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel2); KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3); =20 diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index b7f32305f14a..1f978fddaeed 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1106,8 +1106,7 @@ static void tb_dp_dprx_work(struct work_struct *work) mutex_unlock(&tb->lock); } =20 - if (tunnel->callback) - tunnel->callback(tunnel, tunnel->callback_data); + tunnel->callback(tunnel, tunnel->callback_data); tb_tunnel_put(tunnel); } =20 @@ -1120,15 +1119,10 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunne= l) tb_tunnel_get(tunnel); =20 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); =20 - if (tunnel->callback) { - tunnel->dprx_timeout =3D dprx_timeout_to_ktime(dprx_timeout); - queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0); - return -EINPROGRESS; - } - - return tb_dp_is_usb4(tunnel->src_port->sw) ? - tb_dp_wait_dprx(tunnel, dprx_timeout) : 0; + return -EINPROGRESS; } =20 static void tb_dp_dprx_stop(struct tb_tunnel *tunnel) @@ -1579,20 +1573,28 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) * @tb: Pointer to the domain structure * @in: DP in adapter * @alloc_hopid: Allocate HopIDs from visited ports + * @callback: Callback that is called when the DP tunnel is fully + * activated (or there is an error) + * @callback_data: Data for @callback * * If @in adapter is active, follows the tunnel to the DP out adapter * and back. Returns the discovered tunnel or %NULL if there was no - * tunnel. + * tunnel. See tb_tunnel_alloc_dp() for @callback. * * Return: Pointer to &struct tb_tunnel or %NULL if no tunnel found. */ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, - bool alloc_hopid) + bool alloc_hopid, + void (*callback)(struct tb_tunnel *, void *), + void *callback_data) { struct tb_tunnel *tunnel; struct tb_port *port; struct tb_path *path; =20 + if (WARN_ON(!callback)) + return NULL; + if (!tb_dp_port_is_enabled(in)) return NULL; =20 @@ -1608,6 +1610,9 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb= , struct tb_port *in, tunnel->alloc_bandwidth =3D tb_dp_alloc_bandwidth; tunnel->consumed_bandwidth =3D tb_dp_consumed_bandwidth; tunnel->src_port =3D in; + tunnel->callback =3D callback; + tunnel->callback_data =3D callback_data; + INIT_DELAYED_WORK(&tunnel->dprx_work, tb_dp_dprx_work); =20 path =3D tb_path_discover(in, TB_DP_VIDEO_HOPID, NULL, -1, &tunnel->dst_port, "Video", alloc_hopid); @@ -1674,16 +1679,16 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *= tb, struct tb_port *in, * %0 if no available bandwidth. * @max_down: Maximum available downstream bandwidth for the DP tunnel. * %0 if no available bandwidth. - * @callback: Optional callback that is called when the DP tunnel is - * fully activated (or there is an error) - * @callback_data: Optional data for @callback + * @callback: Callback that is called when the DP tunnel is fully + * activated (or there is an error) + * @callback_data: Data for @callback * * Allocates a tunnel between @in and @out that is capable of tunneling - * Display Port traffic. If @callback is not %NULL it will be called - * after tb_tunnel_activate() once the tunnel has been fully activated. - * It can call tb_tunnel_is_active() to check if activation was - * successful (or if it returns %false there was some sort of issue). - * The @callback is called without @tb->lock held. + * Display Port traffic. The @callback is called after tb_tunnel_activate() + * once the tunnel has been fully activated. It can call + * tb_tunnel_is_active() to check if activation was successful (or if it + * returns %false there was some sort of issue). The @callback is called + * without @tb->lock held. * * Return: Pointer to @struct tb_tunnel or %NULL in case of failure. */ @@ -1698,7 +1703,7 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, s= truct tb_port *in, struct tb_path *path; bool pm_support; =20 - if (WARN_ON(!in->cap_adap || !out->cap_adap)) + if (WARN_ON(!in->cap_adap || !out->cap_adap || !callback)) return NULL; =20 tunnel =3D tb_tunnel_alloc(tb, 3, TB_TUNNEL_DP); diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 4878763a82b3..7d1d255ab5a7 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -66,8 +66,8 @@ enum tb_tunnel_state { * @dprx_canceled: Was DPRX capabilities read poll canceled * @dprx_timeout: If set DPRX capabilities read poll work will timeout aft= er this passes * @dprx_work: Worker that is scheduled to poll completion of DPRX capabil= ities read - * @callback: Optional callback called when DP tunnel is fully activated - * @callback_data: Optional data for @callback + * @callback: Callback called when DP tunnel is fully activated + * @callback_data: Data for @callback * @paths: All paths required by the tunnel */ struct tb_tunnel { @@ -117,7 +117,9 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, st= ruct tb_port *up, bool tb_tunnel_reserved_pci(struct tb_port *port, int *reserved_up, int *reserved_down); struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, - bool alloc_hopid); + bool alloc_hopid, + void (*callback)(struct tb_tunnel *, void *), + void *callback_data); struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, struct tb_port *out, int link_nr, int max_up, int max_down, --=20 2.55.0 From nobody Mon Sep 28 09:59:44 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 8EE6829ACCD; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=YmQG7RsG83lXQkQv09oW9pTIDXi/wS8aYYYnsqqvu3Us2Zj3KN3jA/Mz5/C4KEHxEuylFAGf50wcN8lP2KoQ7vUtWaU0Vs5ur+IukqA9+miv4ikGQ5/QsVXe+YTnrDbALG049WFgT0xv0JfJI6ImcQRbYdcaUL9XPyJM5aaa7zE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=VJZIeF5PZQvYQEjzLXTR8wV0qkJBVGUXFDvmExnY1Y4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gGHBYM9OBDUsyF1zGJqN7Rw4f7LrmyUt30DGsgQHOwm+dn1r4dI9EPI1/5+w6fstTOl8cM8KgmePDcEgv30dNzKodbodIegsDDdq1WX5e2g8qSKNTSMy41OJ8T6ZzAt64fZpFHScr2eCImX3J6Ax0WaPnwfs1IsFr2qi5C4LEHU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j89KZNTO; 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="j89KZNTO" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4EFDBC2BD01; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=VJZIeF5PZQvYQEjzLXTR8wV0qkJBVGUXFDvmExnY1Y4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=j89KZNTOlyTs4ANQEZohXumrAV9AnB89vtKxXmdV90C1O5g+g0H2A6ep22vzdFbT9 GLCXIk3mcCGNrZQvxIvOsX3bMbUUadC40bbQgGUTJ8KpSr0Om/zqNLNcVpE+WW98BQ vl8nzy1DGAQiQjLAhaP13RwA8qvmiZEh54FvWnyY+7uJnXHpMQhaHeEc1olOXiGs4i uYYBHkbmcKXvgd/yOhwJgYwVoYlpw30TIQiy7Vav7/gxLsi2YKnzQ26YPe+wUEGqjg oPsvu7/Bch1w23wrvDugut5tnjZT8ciJ+2yFZ7gcRklJ18s01Cem6M5FbSNGSuxURQ 5PidKCaNO1Lfw== 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 38AF5C5DF81; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:16 +0200 Subject: [PATCH v2 3/7] 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: <20260823-b4-tbt-fixes-v2-3-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3650; i=sven@kernel.org; h=from:subject:message-id; bh=VJZIeF5PZQvYQEjzLXTR8wV0qkJBVGUXFDvmExnY1Y4=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dLzuu8h3bg9L7s6bFXBQrvwj+2LdSe+3pAXWn0ov9 WZmWDe1o5SFQYyLQVZMkWX7fnvTJw/fCC7ddOk9zBxWJpAhDFycAjCRgxYM/13aRFye1d6tjVK+ bC7Ses0lbOq30vd3pq6YeVz6fLBN3lyG/xH3nJee5Ttjqm+82+7a2i4bt3dLn96atHjCdMXrARM Mb7EBAA== 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. This can be triggered whenever a DP tunnel is torn down before the DPRX read has completed, e.g. by unplugging within the timeout, and then 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 29b9879c40d8..ef4413581b2a 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1966,8 +1966,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, @@ -2028,8 +2026,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; @@ -2050,7 +2047,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 1f978fddaeed..00c5a1933544 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1108,15 +1108,17 @@ static void tb_dp_dprx_work(struct work_struct *wor= k) =20 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) { /* - * Bump up the reference to keep the tunnel around. It will be - * dropped in tb_dp_dprx_stop() once the tunnel is deactivated. + * 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); @@ -1127,11 +1129,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 09:59:44 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 9724E344DAD; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=lo77byD7iB87i2zHn/VrI27LVmsVDiA7U1hFgVVPIhpv1eNeXZgxBo7pDAEORyQex4JWJzGpq5mjpg38tcM8/SmfX+a2sVHSig7qbUIRe/VNGgHviZ1S/Hg2Az1JwiRU9tH7ldowzwGyeOsE35q1NGFnzhla042PIA8Z3JQExtw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=J0GZi+6NbVpkFqO2Qu/YQNxbs1qAk3UJgajlm5nEG5M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=K97WNlFM838KcB7OKMnpmxi0VjfG1P9A9a18O84SNEa8t5FkTlK+eZURZHWnnz4g8jC99G1zuoiLcu4dIagd85Lyl1Th57vzPVLoRcgMm1o3ma5yhBjB3V83nU5AapnmXzBIOqauCvIrLwthsLcMrzj2ah2SKMB4xd2QAXtJ6dc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c9quTQeQ; 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="c9quTQeQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 674F6C32781; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=J0GZi+6NbVpkFqO2Qu/YQNxbs1qAk3UJgajlm5nEG5M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=c9quTQeQFE+B9xcdvjV1O6Ba5tMEsxTviaKT/V1UJXyn046RRpLXVuTFRGqAYOr2b +JRuEMfmel2iiTZ9YmwBD1uClhPVpwZzYeKeUd8cRfSzzYUXKuvgdqOPa9phhB/zie aS1aXFgsQmR/0zbOd3pGr6Do3V6W7Rywy04Gm/FlNPJH+qbtV6Wc8hE/fBnyBYUp9N pIyuHThgpZ9KVyickzWlny4DOGC2B1bYJGYnxcOhJNtAxXD76Kk/6zlV6nGI9VGFzT iN3+eOwfD3kIAIgjw0Gjh4ckOL+/KHVAVgOnUDzQlEpPk8fz1aFVy+SI5PrBLVN0Mg iL/ynoP+DvRyw== 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 521DAC5DF8C; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:17 +0200 Subject: [PATCH v2 4/7] 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: <20260823-b4-tbt-fixes-v2-4-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3399; i=sven@kernel.org; h=from:subject:message-id; bh=J0GZi+6NbVpkFqO2Qu/YQNxbs1qAk3UJgajlm5nEG5M=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dMKdTxt3ZgendsYrfXa/EfH29MR1pzfIrjbMtH8aV 8Wn9zqvo5SFQYyLQVZMkWX7fnvTJw/fCC7ddOk9zBxWJpAhDFycAjCRTxmMDFdWN5zNMv/lLBjw IW4P/7RZ9d9F1dniP3sKX75uXOVXbsnwh9fqR0WtO3ezO1N7z4XfZ8K/WxdXLr2gX7naKsWpKYq dEwA= 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 has already been torn down while the domain is suspending or going away. This can be hit by cancelling the DPRX read from outside the ordered tb->wq: During suspend tb_disconnect_and_release_dp does just this and with a later patch tb_stop will do it as well. The latter in combination with the Apple NHI where the DPRX read never completed is how I hit this. 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 ef4413581b2a..088323cd876d 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1912,6 +1912,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 00c5a1933544..5f536635908f 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 tunnel->callback(tunnel, tunnel->callback_data); tb_tunnel_put(tunnel); @@ -1121,6 +1127,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); =20 --=20 2.55.0 From nobody Mon Sep 28 09:59:44 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 BD6D938C438; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=L5G2afXTzBK43jgaimOhKYJAeg+RnnF+O0AZ9iTX9B6PbSufVmN2Hcor6ItIY5ohg+aUU6rvgsv7i0GSB9gTKL0MxlBy1ZWjcffdVy4Cz0WkYfXLujwl5hw97T/s0lBeYK9WyUCUp2Adg54+Gj/zX5zACbFeztdT46UK8qAFIJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=Gf7s+iDVEY9i7s48leCOPqnKX0wFtaHwnlaLaAMjjTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=f14nvGzw36YyTm/8+yA8F2Rk8ogeu+owt3EtlHBucLLkUxhCLc+x4NkVJximcsqFizCj3/M4AMIMnVbaI5R6xhr6F2r2ZBu+Uvvx8NpdAynlCFuh54F3IjncZnW+wk7A2zpDb9IknvcTq8GTFMKUo5Lcpm5Qc+gUNF/Il9Z6okk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P9kEyPLF; 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="P9kEyPLF" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7D6E8C2BCFF; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=Gf7s+iDVEY9i7s48leCOPqnKX0wFtaHwnlaLaAMjjTI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=P9kEyPLFU5Bk7v2yu0OReo2urXS75n8PFY0UZH5S5wd5hI4MYMMHlx+5o5HIYS92J r5lwUYcwlNDa7+6qKgnR5238NE4fxnZ+wSIPU3VlLZz2b+DWjJ3oR5JO/BVIJ7o6f8 FW9sFCLw3qvC/sfKwTkvJvgTa1Ycb6HZLJQ5AbInCtQgsH8FI9Ox6t5rG5TWPafwH7 BgM2gCbcISANYZBMrVIzXVKev3B7dYPwwziVRUCimtDWj6ANpOYN1u/VJbNUMpYfVK asBrFEuFSFnLU5zvT09xp8xblmcKf/qKzd/smMhh4t02W1ZFn5gmFIliSHPDEaXbF9 O/Oz7M5A5QqRw== 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 6B677C5DF97; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:18 +0200 Subject: [PATCH v2 5/7] thunderbolt: Mark discovered tunnels as active 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: <20260823-b4-tbt-fixes-v2-5-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1478; i=sven@kernel.org; h=from:subject:message-id; bh=Gf7s+iDVEY9i7s48leCOPqnKX0wFtaHwnlaLaAMjjTI=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dOIBW5fuoJ+bOxYy9C49tkM96Oy5pZ3zTIQX/74vG XSBZXNlRykLgxgXg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAiJg0M/91+/I1fI8E7TyZA 1uqYn8//7+YPZy0zXs76dPMSEfe9N28z/E/mvPpG7K/4qxOLO+Wfvf8QoNIptGeHy/2odUYzN2i d4ecGAA== 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 Discovered tunnels that have been activated by whatever was running before us stay in TB_TUNNEL_INACTIVE until hibernation restore such that anything depending on tb_tunnel_is_active() skips them. Mark them active during discovery instead. These now also emit TUNNEL_EVENT=3Dactivated uevents during discovery. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/tunnel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 5f536635908f..3785e29cf92b 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -507,6 +507,7 @@ struct tb_tunnel *tb_tunnel_discover_pci(struct tb *tb,= struct tb_port *down, goto err_deactivate; } =20 + tb_tunnel_set_active(tunnel, true); tb_tunnel_dbg(tunnel, "discovered\n"); return tunnel; =20 @@ -1671,6 +1672,7 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb= , struct tb_port *in, =20 tb_dp_dump(tunnel); =20 + tb_tunnel_set_active(tunnel, true); tb_tunnel_dbg(tunnel, "discovered\n"); return tunnel; =20 @@ -2299,6 +2301,7 @@ struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *= tb, struct tb_port *down, tb_usb3_reclaim_available_bandwidth; } =20 + tb_tunnel_set_active(tunnel, true); tb_tunnel_dbg(tunnel, "discovered\n"); return tunnel; =20 --=20 2.55.0 From nobody Mon Sep 28 09:59:44 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 BE4A338D3E2; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=sy33iEOLicgeQigKXsT8Yu3AvcErC+ddphoQQ+PjZ7Lbh+0qEju+kTbV2L2pVgiC6kO2/S/qZ0FtM0EGuRh736qe86Kip16/+BzdWrOw6b1KLsZb/NEMtc9QyXy06yd1fKs6fM7nXeSEtbySkSJc/nnzWJuxI/ibLXcojbuJRnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=gM3ljiZ7OeI79gnw2yBh74ko5W+e/3qUprdtBSuU7QU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BxmryeswNCbpyQQyf6edFiXOin3cZr/XG1ZWPpdhmDeDwfh7HLUM9aSWY/3pYQtpqFPWk8y5esaqvLS4eSg8N1kI+t23hJRH4jY/ZzT7nksn+2GxGy9M9RnuNys9nOCW7dJty33wEX5YSIBNvCb8wLJ1wBaMnhJVEIZ/0y6OJEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JB+X6rFQ; 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="JB+X6rFQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 97477C2BD04; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=gM3ljiZ7OeI79gnw2yBh74ko5W+e/3qUprdtBSuU7QU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JB+X6rFQB2twuQ/dHmEj9yp0yOkdPinwMzFDVC9/BhVyhHRQ7KxsUyVvd8TzVHyqj UFVM/54kXN5zCcu7IZ43syuFSep8n7Fn3owdNOI1VT6dGj5p6X4ejcvxEKPFCCjCen Qf89AMLUCZTACkqcpeYVwMOPUITY1v5fUPYEs8+oeHeIbRSKAok5G1uZD4vF6MHs10 /zruOhcyd2If3+lBMUoVCZWH2f+N/NiTi3Jk5BP7MNcB0kdT39M4oq8U8jZFo+DwB6 uS8YkHSEYzoij7sIhAyBNj4u5VRcODkwlSS6QVT1rTbnjtizs+spSHb3T6BJe/PTCN zAKPCdaX+KFsQ== 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 82164C5DF9C; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:19 +0200 Subject: [PATCH v2 6/7] thunderbolt: Tear down inactive DP tunnels 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: <20260823-b4-tbt-fixes-v2-6-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2083; i=sven@kernel.org; h=from:subject:message-id; bh=gM3ljiZ7OeI79gnw2yBh74ko5W+e/3qUprdtBSuU7QU=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dNJ3hvKdM2vehJtY7ggJibjsWzBlSvrhTIGrAef7O xVE6k53lLIwiHExyIopsmzfb2/65OEbwaWbLr2HmcPKBDKEgYtTACZyeRXDX9Gku7ODwj1fHXH/ sbzpU+SdK/YvFOL6bmudKHuV0sp0m5vhr4zU/8mztE4UTdnjfJ3t5KPH3RWGv6Lipm6aVPnoini JLi8A 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. Tear down DP tunnels that are not active yet as well which also cancels that work. Tunnels for displays that are already alive are untouched and keep 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 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 088323cd876d..921adba3544f 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -2958,12 +2958,14 @@ static void tb_stop(struct tb *tb) /* tunnels are only present after everything has been initialized */ list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) { /* - * DMA tunnels require the driver to be functional so we - * tear them down. Other protocol tunnels can be left - * intact. + * DMA tunnels and DP tunnels which are not yet active require + * the driver to be functional so we tear them down. + * Other protocol tunnels can be left intact. */ if (tb_tunnel_is_dma(tunnel)) tb_tunnel_deactivate(tunnel); + else if (tb_tunnel_is_dp(tunnel) && !tb_tunnel_is_active(tunnel)) + tb_tunnel_deactivate(tunnel); tb_tunnel_put(tunnel); } tb_switch_remove(tb->root_switch); --=20 2.55.0 From nobody Mon Sep 28 09:59:44 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 DBAE138F24D; Sun, 23 Aug 2026 16:10:15 +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=1787501415; cv=none; b=U7Xgfg87X+jFC+HeYpXoo15T1LEaJGRaQvQWu5Zlc4eq0yAQ95MO4MrqTwJvNWts519GLKbFCuFPg/cnuzh65fVx+wpyshwL7m4Cn32lGYSFdhIQk8EPwxEEN5XdHOsSVyh2aNeHeWEtnyOPd/0coY8Pv33zmtElQEN6BGlSNHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787501415; c=relaxed/simple; bh=4/gZflZqyfX3VI0ASxHBldunkbN3iGh6yKI7giShHRE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NGCuuTRt52I48QWvzcN6tF/IbODLPlXJYvh49srzYS2aGTUDSh+cUhvy579s4vNvLN/3x3VUycPkdyvUCvJbEmZSJjvHbojhN5SuMRHwUp1nDK8q45i3VLzL3LkgDmRKmAYDJUtcyZxfuy77iMEdFMSO/0YYNDJOcWMNHp9DznQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Z5FTSr/v; 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="Z5FTSr/v" Received: by smtp.kernel.org (Postfix) with ESMTPS id B21EDC2BCFC; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787501415; bh=4/gZflZqyfX3VI0ASxHBldunkbN3iGh6yKI7giShHRE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Z5FTSr/vNytzkdH2iny8wdq5jPl0tezlqY3qXN0YG/gBgkXHk/JS/SX5ianxkaN/S pm9JdDlAWvcLwrrMMU/EClmieUb1XqZbGOZJsPNPdhyiBe9ZDebBt3+9JxVE/cdNCE iMOzI7/bsXVH1/YdRnX15E/8Cw6GQnVWNRmmicH91jCxvRvRxXgzDh9tO553qev3iO fsjt3Ikk1VStF7w5+GEL+53B2l8Gxj07qwPAJg+tQvLW5A+KIEeDzklr2B1Y96aNl4 rW2pW34rimFhIAKupWv3FSlOYsOg43ZZbwSv4UEj0+2C1joMot4QgoasEM6eufZQo1 oTAldXnx8HiGg== 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 9F4A2C5DF81; Sun, 23 Aug 2026 16:10:15 +0000 (UTC) From: Sven Peter Date: Sun, 23 Aug 2026 18:09:20 +0200 Subject: [PATCH v2 7/7] thunderbolt: Drop the DP tunnel activation callback data 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: <20260823-b4-tbt-fixes-v2-7-26a18a426c9f@kernel.org> References: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> In-Reply-To: <20260823-b4-tbt-fixes-v2-0-26a18a426c9f@kernel.org> To: Andreas Noever , Mika Westerberg , Yehezkel Bernat Cc: Mika Westerberg , Konrad Dybcio , asahi@lists.linux.dev, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=11508; i=sven@kernel.org; h=from:subject:message-id; bh=4/gZflZqyfX3VI0ASxHBldunkbN3iGh6yKI7giShHRE=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ1a3dMrbozeLWpMy+gI43ogs7LNWXTVv1ysr7TM6pst+L G3d6p3TUcrCIMbFICumyLJ9v73pk4dvBJduuvQeZg4rE8gQBi5OAZjI0jMMv5imV7nse7OVt3Su 5uY7HBNPhrv03spZUV0z/+ZVd+bn57wY/he8czLNmnBgh1xxy4HGUsv3gZtvZmhXnxZ5cXXHy2+ 3nnEAAA== 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 The callback data is always the domain the tunnel belongs to which the callback can just take from the tunnel itself. Signed-off-by: Sven Peter --- drivers/thunderbolt/tb.c | 10 +++++----- drivers/thunderbolt/test.c | 24 ++++++++++++------------ drivers/thunderbolt/tunnel.c | 12 +++--------- drivers/thunderbolt/tunnel.h | 10 +++------- 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 921adba3544f..40a5a3ebb31d 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -89,7 +89,7 @@ static void tb_dp_resource_unavailable(struct tb *tb, str= uct tb_port *port, const char *reason); static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 por= t, int retry, unsigned long delay); -static void tb_dp_tunnel_active(struct tb_tunnel *tunnel, void *data); +static void tb_dp_tunnel_active(struct tb_tunnel *tunnel); =20 static void tb_queue_hotplug(struct tb *tb, u64 route, u8 port, bool unplu= g) { @@ -387,7 +387,7 @@ static void tb_switch_discover_tunnels(struct tb_switch= *sw, switch (port->config.type) { case TB_TYPE_DP_HDMI_IN: tunnel =3D tb_tunnel_discover_dp(tb, port, alloc_hopids, - tb_dp_tunnel_active, tb); + tb_dp_tunnel_active); tb_increase_tmu_accuracy(tunnel); break; =20 @@ -1905,11 +1905,11 @@ static struct tb_port *tb_find_dp_out(struct tb *tb= , struct tb_port *in) return NULL; } =20 -static void tb_dp_tunnel_active(struct tb_tunnel *tunnel, void *data) +static void tb_dp_tunnel_active(struct tb_tunnel *tunnel) { struct tb_port *in =3D tunnel->src_port; struct tb_port *out =3D tunnel->dst_port; - struct tb *tb =3D data; + struct tb *tb =3D tunnel->tb; =20 mutex_lock(&tb->lock); =20 @@ -2038,7 +2038,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); + available_down, tb_dp_tunnel_active); if (!tunnel) { tb_port_dbg(out, "could not allocate DP tunnel\n"); goto err_reclaim_usb; diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index fc3f647bf664..9e128c26f003 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -1398,7 +1398,7 @@ static void tb_test_tunnel_pcie(struct kunit *test) tb_tunnel_put(tunnel1); } =20 -static void tb_test_dp_tunnel_active(struct tb_tunnel *tunnel, void *data) +static void tb_test_dp_tunnel_active(struct tb_tunnel *tunnel) { } =20 @@ -1423,7 +1423,7 @@ static void tb_test_tunnel_dp(struct kunit *test) out =3D &dev->ports[13]; =20 tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1470,7 +1470,7 @@ static void tb_test_tunnel_dp_chain(struct kunit *tes= t) out =3D &dev4->ports[14]; =20 tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1521,7 +1521,7 @@ static void tb_test_tunnel_dp_tree(struct kunit *test) out =3D &dev5->ports[13]; =20 tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1587,7 +1587,7 @@ static void tb_test_tunnel_dp_max_length(struct kunit= *test) out =3D &dev12->ports[13]; =20 tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); @@ -1658,7 +1658,7 @@ static void tb_test_tunnel_3dp(struct kunit *test) out3 =3D &dev4->ports[14]; =20 tunnel1 =3D tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_TRUE(test, tunnel1 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, in1); @@ -1667,7 +1667,7 @@ static void tb_test_tunnel_3dp(struct kunit *test) KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 3); =20 tunnel2 =3D tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_TRUE(test, tunnel2 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, in2); @@ -1676,7 +1676,7 @@ static void tb_test_tunnel_3dp(struct kunit *test) KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 4); =20 tunnel3 =3D tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_TRUE(test, tunnel3 !=3D NULL); KUNIT_EXPECT_EQ(test, tunnel3->type, TB_TUNNEL_DP); KUNIT_EXPECT_PTR_EQ(test, tunnel3->src_port, in3); @@ -1775,7 +1775,7 @@ static void tb_test_tunnel_port_on_path(struct kunit = *test) out =3D &dev5->ports[13]; =20 dp_tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel); =20 KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, in)); @@ -2208,7 +2208,7 @@ static void tb_test_credit_alloc_dp(struct kunit *tes= t) out =3D &dev->ports[14]; =20 tunnel =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, tunnel); KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)3); =20 @@ -2445,7 +2445,7 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL1(struct ku= nit *test, in =3D &host->ports[5]; out =3D &dev->ports[13]; dp_tunnel1 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel1); KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3); =20 @@ -2483,7 +2483,7 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL2(struct ku= nit *test, in =3D &host->ports[6]; out =3D &dev->ports[14]; dp_tunnel2 =3D tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0, - tb_test_dp_tunnel_active, NULL); + tb_test_dp_tunnel_active); KUNIT_ASSERT_NOT_NULL(test, dp_tunnel2); KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3); =20 diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 3785e29cf92b..cbffb1e612b6 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1113,7 +1113,7 @@ static void tb_dp_dprx_work(struct work_struct *work) } mutex_unlock(&tb->lock); =20 - tunnel->callback(tunnel, tunnel->callback_data); + tunnel->callback(tunnel); tb_tunnel_put(tunnel); tb_domain_put(tb); } @@ -1589,7 +1589,6 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) * @alloc_hopid: Allocate HopIDs from visited ports * @callback: Callback that is called when the DP tunnel is fully * activated (or there is an error) - * @callback_data: Data for @callback * * If @in adapter is active, follows the tunnel to the DP out adapter * and back. Returns the discovered tunnel or %NULL if there was no @@ -1599,8 +1598,7 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) */ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, bool alloc_hopid, - void (*callback)(struct tb_tunnel *, void *), - void *callback_data) + void (*callback)(struct tb_tunnel *)) { struct tb_tunnel *tunnel; struct tb_port *port; @@ -1625,7 +1623,6 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb= , struct tb_port *in, tunnel->consumed_bandwidth =3D tb_dp_consumed_bandwidth; tunnel->src_port =3D in; tunnel->callback =3D callback; - tunnel->callback_data =3D callback_data; INIT_DELAYED_WORK(&tunnel->dprx_work, tb_dp_dprx_work); =20 path =3D tb_path_discover(in, TB_DP_VIDEO_HOPID, NULL, -1, @@ -1696,7 +1693,6 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb= , struct tb_port *in, * %0 if no available bandwidth. * @callback: Callback that is called when the DP tunnel is fully * activated (or there is an error) - * @callback_data: Data for @callback * * Allocates a tunnel between @in and @out that is capable of tunneling * Display Port traffic. The @callback is called after tb_tunnel_activate() @@ -1710,8 +1706,7 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb= , struct tb_port *in, struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, struct tb_port *out, int link_nr, int max_up, int max_down, - void (*callback)(struct tb_tunnel *, void *), - void *callback_data) + void (*callback)(struct tb_tunnel *)) { struct tb_tunnel *tunnel; struct tb_path **paths; @@ -1737,7 +1732,6 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, s= truct tb_port *in, tunnel->max_up =3D max_up; tunnel->max_down =3D max_down; tunnel->callback =3D callback; - tunnel->callback_data =3D callback_data; INIT_DELAYED_WORK(&tunnel->dprx_work, tb_dp_dprx_work); =20 paths =3D tunnel->paths; diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 7d1d255ab5a7..28f49f7e9f56 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -67,7 +67,6 @@ enum tb_tunnel_state { * @dprx_timeout: If set DPRX capabilities read poll work will timeout aft= er this passes * @dprx_work: Worker that is scheduled to poll completion of DPRX capabil= ities read * @callback: Callback called when DP tunnel is fully activated - * @callback_data: Data for @callback * @paths: All paths required by the tunnel */ struct tb_tunnel { @@ -104,8 +103,7 @@ struct tb_tunnel { bool dprx_canceled; ktime_t dprx_timeout; struct delayed_work dprx_work; - void (*callback)(struct tb_tunnel *tunnel, void *data); - void *callback_data; + void (*callback)(struct tb_tunnel *tunnel); =20 struct tb_path *paths[] __counted_by(npaths); }; @@ -118,13 +116,11 @@ bool tb_tunnel_reserved_pci(struct tb_port *port, int= *reserved_up, int *reserved_down); struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, bool alloc_hopid, - void (*callback)(struct tb_tunnel *, void *), - void *callback_data); + void (*callback)(struct tb_tunnel *)); struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, struct tb_port *out, int link_nr, int max_up, int max_down, - void (*callback)(struct tb_tunnel *, void *), - void *callback_data); + void (*callback)(struct tb_tunnel *)); struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, struct tb_port *dst, int transmit_path, int transmit_ring, int receive_path, --=20 2.55.0