From nobody Sat Sep 26 22:34:42 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 CD65235836E; Sat, 29 Aug 2026 08:08:50 +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=1787990930; cv=none; b=mcbQ8HQLGLmCJK/Y/p5PNAeGzbl2J52nFwYZcP4oZhyk1O3x4pIxspV1kWC4rxQf7DRo2P4ZikAxeH+fJ0x3p6xYYKgYVHuiNvDbpIQhhnCQFkcc0niM/uCD9zuwjXcdDRpsaTNFp8BCeMMWeRBAmUkE36KcTmh2AAEpwnG8Jbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990930; c=relaxed/simple; bh=MOWklr/9/zxO0RK1ptJ7O/V6sWasLOgUeySDBc1yB98=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=t0uOv1PDas7CflD9OizIaA53ok9VvqnsB3G5jyjat8yM5vlib7A7nUpWMYwfqwHB6073HEJWvQ2eIteKR2paOAjxlMKKvEnGxDT4lDwohdolV3fU6ixU5R6LbTA7M9NQmUUjOKklFzvrzMxfemzFxjxNDWKOSUMfwW/S8czZxq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bYTf0obU; 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="bYTf0obU" Received: by smtp.kernel.org (Postfix) with ESMTPS id 62CD0C2BCF6; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=MOWklr/9/zxO0RK1ptJ7O/V6sWasLOgUeySDBc1yB98=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bYTf0obU5YYiiVGb1EDK5whrGIEPZ5x2V4AMnsCpClqlEKaQ9gEek8H+3ttu/lIyR BrGLVxrnNZh//SzaPnUSfEx6hciW14LKTtREAW9ZfmGy+fS/wnmn1CNMpvPIJtW0ie ofy9IjN++Gh3cG8Aw0msR/Vf1XHmCWvXMbwv7vEEUWXCFZrM6Ud/SDgkOZVqazP7zx wwLXQNzfi2ukuXnKFd8nJ0oJqlopRWSyf+tq3l8S3fo47glCcnAbWAOYHF6Pe1iPaC vuoh8P8VLZyno79epDiasgN8XoF0ekJPIS6BcIzSXQcanMX5Y2xEQomOLkAor9t00H /D/43dfFgJe8g== 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 43B37C61DCB; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:33 +0200 Subject: [PATCH v3 1/7] thunderbolt: Hold a router reference for each allocated HopID 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: <20260829-b4-tbt-fixes-v3-1-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=4048; i=sven@kernel.org; h=from:subject:message-id; bh=MOWklr/9/zxO0RK1ptJ7O/V6sWasLOgUeySDBc1yB98=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyd3veqeH3Ww13ZVas2f1JYF0IeVnP8WTD99SyNldm 3B+mr5ERykLgxgXg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAixk8YGdqYBJiehU2ax+K+ d7qakdb72ZI7/DgWTc6VbrAN5ZTeOZuRodPU8sEf//Ot3qWKKZUSAbekDz2Pfv7pQ/V8I79qfvH d7AA= 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 a router reference whenever an input or output HopID is allocated and drop it again after the HopID is released. This keeps the ports and their HopID IDAs alive for as long as they are used. The KUnit tests allocate routers without ever registering their devices so initialize the embedded struct device there as well and drop its initial reference when the test is finished. Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asy= nchronously") Cc: stable@vger.kernel.org Signed-off-by: Sven Peter --- drivers/thunderbolt/switch.c | 9 ++++++++- drivers/thunderbolt/test.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index a830c82bb905..217e18f8a7c7 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -765,6 +765,7 @@ static int tb_port_alloc_hopid(struct tb_port *port, bo= ol in, int min_hopid, { int port_max_hopid; struct ida *ida; + int ret; =20 if (in) { port_max_hopid =3D port->config.max_in_hop_id; @@ -784,7 +785,11 @@ static int tb_port_alloc_hopid(struct tb_port *port, b= ool in, int min_hopid, if (max_hopid < 0 || max_hopid > port_max_hopid) max_hopid =3D port_max_hopid; =20 - return ida_alloc_range(ida, min_hopid, max_hopid, GFP_KERNEL); + ret =3D ida_alloc_range(ida, min_hopid, max_hopid, GFP_KERNEL); + if (ret >=3D 0) + tb_switch_get(port->sw); + + return ret; } =20 /** @@ -823,6 +828,7 @@ int tb_port_alloc_out_hopid(struct tb_port *port, int m= in_hopid, int max_hopid) void tb_port_release_in_hopid(struct tb_port *port, int hopid) { ida_free(&port->in_hopids, hopid); + tb_switch_put(port->sw); } =20 /** @@ -833,6 +839,7 @@ void tb_port_release_in_hopid(struct tb_port *port, int= hopid) void tb_port_release_out_hopid(struct tb_port *port, int hopid) { ida_free(&port->out_hopids, hopid); + tb_switch_put(port->sw); } =20 static inline bool tb_switch_is_reachable(const struct tb_switch *parent, diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 05652ee82fbf..799ada97cbc9 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -33,6 +33,18 @@ 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 void tb_test_switch_put(void *data) +{ + struct tb_switch *sw =3D data; + + put_device(&sw->dev); +} + static struct tb_switch *alloc_switch(struct kunit *test, u64 route, u8 upstream_port, u8 max_port_number) { @@ -44,6 +56,15 @@ static struct tb_switch *alloc_switch(struct kunit *test= , u64 route, if (!sw) return NULL; =20 + /* + * HopID allocations take a reference to their routers and those devices + * have to be initialized for that to work. + */ + sw->dev.release =3D tb_test_switch_release; + device_initialize(&sw->dev); + if (kunit_add_action_or_reset(test, tb_test_switch_put, sw)) + return NULL; + 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 Sat Sep 26 22:34:42 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 CD5C934F259; Sat, 29 Aug 2026 08:08:50 +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=1787990930; cv=none; b=hVkC6+aQz27j85O7yLYXjDSQyLnaeC+fe1rzBxdLi/qVPJIgwDkJ34RTAyOuZoSqXiOKGZ53c6fk4f1O/qCH2oYM1EnExsjOKRCI7sENaB0D+U5zcJcP4rYEbw8jJ4s3Et3AUFw52DGpN6kDcDIMnX2uDybYCpC9JZzU9dHYEtw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990930; c=relaxed/simple; bh=drUQ/9LCnjgsH8dTdZZsgx0jQ7RPPm7Ngc2sH0x40Uo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WlZvcAJzq3xWVZpi+VZLh0jmYUhwkAWdtnoNLXmKrRLM5BOot7y0lMZXUvFqCgliUjDFFoF8t4JHMtxoDZF+Ou7Qa9P2Ipd9ayVujBsYaHcrJZRr2+BNp4MTgG8TWBUHuHIKzWtmwFT3xjTshcxh/1YVY+UOP3rdQLnj0THFqcU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=drSv4qr4; 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="drSv4qr4" Received: by smtp.kernel.org (Postfix) with ESMTPS id 73174C2BCF7; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=drUQ/9LCnjgsH8dTdZZsgx0jQ7RPPm7Ngc2sH0x40Uo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=drSv4qr4KHD5JCEp4KGvwpPx1I7VDVCprr+/q0DQ+6GtutTUqCixDnX7+6I6kOF0K WXMzr5grDENZKArJJlYQMhJG7KyLy93o0tgWrgiWiPsrx8IjESCKg0/y95mFdjONcg /f2f66qep3bIfEcPJXAD0cf2sKKJi4im3vmoxYcmul7WKveA+BY9TmnJGYHPd3wRoM ZOZPdRB276f/0uOPXMponYqS0+k8KtO3+xwNs6pckaK4XhNTrZ1SfLJinEYIcehah9 3PkdLKTnaOhfj3QrCfQYcSN/HjXOVWH7ERQImk8U3l1lC+vnRgtrJOSfDkLAoU/no0 OZg1C9lBqYwBg== 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 55A90C61DD7; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:34 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-2-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=13575; i=sven@kernel.org; h=from:subject:message-id; bh=drUQ/9LCnjgsH8dTdZZsgx0jQ7RPPm7Ngc2sH0x40Uo=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyT08eduV992rnJPVwnX9Qh9X+IvSiAqbF22+zJZlN +Tn1k/uKGVhEONikBVTZNm+3970ycM3gks3XXoPM4eVCWQIAxenAEzksBsjwy4j20tZxfbtt5+U isrxuyXe1Ne6VD4vtc02w+ru7WXWbIwMjx8Xsr+bXawg63qeoawydxrH+4gZd79nZggfe7XBsfY sEwA= 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 --- tb_dp_tunnel_active() calls five helpers that are defined later in the file. Moving the entire function up would require forward declarations for all of those, so keep the single forward declaration instead. --- 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 799ada97cbc9..c8c648f31107 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -1407,6 +1407,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; @@ -1427,7 +1431,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); @@ -1473,7 +1478,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); @@ -1523,7 +1529,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); @@ -1588,7 +1595,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); @@ -1658,7 +1666,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); @@ -1666,7 +1675,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); @@ -1674,7 +1684,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); @@ -1772,7 +1783,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)); @@ -2204,7 +2216,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 @@ -2440,7 +2453,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 @@ -2477,7 +2491,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 Sat Sep 26 22:34:42 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 D2FAB374A14; Sat, 29 Aug 2026 08:08:50 +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=1787990930; cv=none; b=kb+wJJ9xXc4VpbMpzibnhaYqdiwxkkNnzohQd6s1EUHsLef0sU8IGR7a8BP/baU5DDdjgKDKOBZZWsPSc+hvpcC/2Sq8Wb97D/EAq5KPPu3BxwYzuBkJpP+dTyn8xOThOnu259Plhpx1tns3MElze3gpVBBZptV4zDjLQRRYvCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990930; c=relaxed/simple; bh=VJZIeF5PZQvYQEjzLXTR8wV0qkJBVGUXFDvmExnY1Y4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=c2qudTwWMua21At0j2Qi9ecvreMNl76lo/oIkKH171RdDbPeOmXamsihjAEUX9FzfYBvi8yzVgtWNpXjLJk713dD9OgJ0W55qAu5g4BvilLdAadO3wi67SjpHmMX8Eo7FQ6doAFfPn5ibmJSPn2klezTBclpLVLKu36fZ8Mbjok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A8Ko/1vt; 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="A8Ko/1vt" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7E87EC2BCFA; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=VJZIeF5PZQvYQEjzLXTR8wV0qkJBVGUXFDvmExnY1Y4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=A8Ko/1vtiT+JgmBA590SN81HqR4YbBCIuuZ9/DhTfJicY1n+cK3drcpujTNGVZ7vK 5Tp1qWwXwKGjdFmajab1h7etSgR5SsjBwq8/mgyJp+PHDxML3EUGNe0lP3e0OgZA7U ZwwmKA99SLfCH+3bYBw5opsZzDEX0cC60ih9AVWFMHhzXh/XvDY9cfax5gDlqJ9HeR sIe1IUwhcNBmPXLT7BRHrLv9PZ0hsVbucbg/pYs0lZUldEgVqKvQVbhxiWpuoNqogU 2fcne2V4gTclX0fgbfzJwvPXikFaO7T6Wm5QWQ4Jamz9liC8kzAGZon8wYvKAmfANe U0fbFweV6lQ7Q== 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 656F5C61DDC; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:35 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-3-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyb0/Jn3P4GkQWJ94yVTRVPWq6ikuhqX5E45cXP3tA s+jDdmrOkpZGMS4GGTFFFm277c3ffLwjeDSTZfew8xhZQIZwsDFKQATUWxi+F+ZcTK+ytOhz9ec yz+z3pDLtyIx9DJvXIL/3ozvUbOePmD4Z9Eq+FPYOrC9d93Px5sLDh37N2lPhu78+fIHWVZl79/ twwIA 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 Sat Sep 26 22:34:42 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 DFE6D376A16; Sat, 29 Aug 2026 08:08:50 +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=1787990931; cv=none; b=Mm0baO/tjGA/ZE8wKExfiW3Lx5rIbm3Qh4DiOzTYiKHPoWosBmpm2fvBBbLqQ87wz0ylTbochd4NtkKZPLszytFDAT7BNHwPkGsgQxMkvUVuuooCP4bSSEcpDGvGG7KUbZBYbzmbdGnuSIPkQdnsvmIcGAopLJ7Y83TRivRbLdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990931; c=relaxed/simple; bh=J0GZi+6NbVpkFqO2Qu/YQNxbs1qAk3UJgajlm5nEG5M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EMhNbyDox+BICuG8MghrcYFAdz/OGgAoNTSHTMHat3GdisZ2XTHjr0eAziuHO4YHGMYPYSD4aTzmsxpsjFbc14xdiC9f6PWSh7cBTThmpJrXtEeNLM/VU4Sqb52+C8ji81T1x0uYwFhO1q8hVo2jNzdN17wKZAZ4DmCT1J8yrCI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TKFRm+PN; 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="TKFRm+PN" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8EE9FC4AF09; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=J0GZi+6NbVpkFqO2Qu/YQNxbs1qAk3UJgajlm5nEG5M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TKFRm+PNG/BVnXw8ZiyqECAm76FWeRCVBMhoUvWr77u+I3+CAMjFZyv83YG28hYT0 pj3so6thq0qPLmXviY8hMuEgxBJqiAHdXJE6dkzP7y8buDf+hV1NaIWbpUVUvT7OnW 3EYS8znmYCvgh7nyTuhk0p8yzruADudzWy3Xad4WCwmMOJgvWgbdwC1bp2/WimrW3t kkc4lDaFi/+YHgtswiJWp22+WazRdOJXlJ5IJaUYRJX1+JRachOA0Ml/6hGKEQ9P81 qQvR0pdkxlOWtjTWZrwF2XA+uHns1kbUh/U21JkPlf8KyesiygOhl15suOce+R5X2b cbwUlpzDRLF9w== 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 7480EC61DDE; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:36 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-4-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyb0Wvu7byw6m5b/RyixhkFvqKJ9+f4tB2EzdnjV9D lO8Cid0lLIwiHExyIopsmzfb2/65OEbwaWbLr2HmcPKBDKEgYtTACaiqs3wV+BTYMrW2id/6jp3 Tzhp2a5hvUwweeuHgxmBqTfvp71+sY+R4WbIyc9r0pX9LsSG/+B7ezbm6toZc29W/2/clBqr9Wt CIDsA 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 Sat Sep 26 22:34:42 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 0A8FE38DC65; Sat, 29 Aug 2026 08:08:51 +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=1787990931; cv=none; b=rtHvdBc24ZkIFsXfgZbg5EaBbUWyU0swXRdvalx5854QLeef/tcpqLO/Q9LmwRTebcHvbNldcOnG1gLCyWamBfeXJFt61FLcgONiC7Div3ghvBNPeoAVE7vJ0ioxcPvKgzXNrItoEapIe+brb4MxfMfA8KB3+PfmDyJvvoyRm3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990931; c=relaxed/simple; bh=Gf7s+iDVEY9i7s48leCOPqnKX0wFtaHwnlaLaAMjjTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eNqk4nMECVbCvBwFMXHjD4s+CiffKrCOEHrcjBDFLPDvLbVAFwFdplTL6dVzmY8Axa4Ws2RfbBDbdRPPT7Lx7grNvPGhvKMumKnlA03LbApnHfbUn4ft7p/W1kwWPp1w/gwCfxbsduPxvqFAz6pcjNXV+xvfQee9+M7w8Viyv6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DZPWzYiS; 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="DZPWzYiS" Received: by smtp.kernel.org (Postfix) with ESMTPS id 99786C2BD05; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=Gf7s+iDVEY9i7s48leCOPqnKX0wFtaHwnlaLaAMjjTI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DZPWzYiS4u8sGNqQNT/Sl3/DEpq+Zq21qrhp/D5HwecLaMHfCE891mGIEP/finNkQ y6ac8dA06WSzjDutIJOMZafVUg74u/bQ50/9TbEaOxUF/fGG3zueNpAGyua3/H5Czo kx/pac0J3A4VTuU9FAh7+7XnMSV5waXrjTU/hhnPFM2dSqOiSDoJassHPIEvYSXb+W iQzPNosHpCsgDF9TpzwX6k8ZVEcjaIW8SEFzIi8t106QSBIQQdEFHZbRrSZF2egL1V kXvfbhEcPJwLpibj3cUMZZxWp4oBfSVYOqjQio7RI37cS/iYO6SELyDxwKrCe5u5M4 tAR7y+p6GAMsQ== 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 8364EC61DDD; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:37 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-5-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyX0SGz9emhE/54XywU+PLC45Pp8cei7vwrZTqacfT vxzsv+ZV0cpC4MYF4OsmCLL9v32pk8evhFcuunSe5g5rEwgQxi4OAVgIs+5Gf7ZZao8ShY5GXjV UnDv0xMOEfFi177r+lY4MHyd5nXtnfsHhn9mc3OWS2QUuS5ap98q9eXwTc8WkeOZ/s/nztwouWt BXicLAA== 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 Sat Sep 26 22:34:42 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 1FB6C3955CA; Sat, 29 Aug 2026 08:08:51 +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=1787990931; cv=none; b=hH62ZLSPFvjG6LFkWuku2ubQ6bGPFkZ/K9VLWDs/l3qlAUV6Aaai36DINzbKlPyEEgcxyWOjEyS3atAr+Aem46/ZpgQdif7UGjpIdO+l8LXxuLay+vsJDLBPg1ZufgbyPX6Gd7A0FadlFUTAkXvpaQBVQZBmHxAY+xMTA8jAws0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990931; c=relaxed/simple; bh=gM3ljiZ7OeI79gnw2yBh74ko5W+e/3qUprdtBSuU7QU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PQLXv4v6C2G588+su962DbfgWSgtk0m/Y2sjWVprwOPZ0GEFMw+9LUoFcaylD+LoBefRvJdKI5DbVGO7fbEVSHKhDrzmdOxWgwrCpNa0GmOEeREwCv83M2P3zQbXRAbyk60w6PRHWn1B2bWZ+QHbS7rOIVhOpTObcl5uayW3Ru0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N8p86tW4; 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="N8p86tW4" Received: by smtp.kernel.org (Postfix) with ESMTPS id B4755C4AF14; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=gM3ljiZ7OeI79gnw2yBh74ko5W+e/3qUprdtBSuU7QU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=N8p86tW4RhUX/uYWoXZ5ls4ZMLK9TVBAx0uQOqwDHfoe+mgxPeCaTmdDbGJ2DUShW Ds7ebhnami/IUI3L4scuCH9p+MYP04z3ba/MbJjpo1HcY3IEkXz8itPyFeFw7KpKvH HGqwzRh0j1uOg6/Y3MVyzB7DuFv6KsRP7teSCrCY++TYOtHr2b9pKEkhQW9DP77Pcj 65m4BXYZI2e+UvpPtEWRbwk1ZTxe+Ep2EgGtiLBmLjHSolqD++f9lCbKtNXbLakpzM weJ3TeEW33d0WgMpTgZqNuVBdHzLWv83/fnbSxihVGfo1b0XQHDFzvJDHXAgFAI7vA KdQgXttrDgNTQ== 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 919E7C61DBE; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:38 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-6-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyf217AeWne+VvSM8pZ3F4dm3jWfzVOTqDrbu1FHYP kexp/J0RykLgxgXg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAisu6MDB+2Zk/dP51x+4rz Z18/XCAWaRK7Ll7uTvTESbefdF6fZZnF8IdL7K3lC87FzPN7ny7d4WnzMHLe2sfGzxa6/U5Q9Gj SMOYGAA== 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 Sat Sep 26 22:34:42 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 1ED283955C9; Sat, 29 Aug 2026 08:08:51 +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=1787990931; cv=none; b=NmupJv2Ra37tAwTrJH4BjW0y+KxG04mcecNZtIoJUjLgbZvzIPWYJHfMwMza9Un5SNM8NdTi/zaJoEXiXzCZAxcQmzYlPxPY7z21+6L5lYVmsSVK2or6Ujik9B3dwWhp0lRbukHqC70YSGAF/DRw1beh8a4KsjWxhhRNuFovCPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787990931; c=relaxed/simple; bh=onwj9ZvmShEMgbw8Rtmke+EWIIMyg7UeYx5VmGnUVLE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hGjgztNrpO5xC0As/qpc/rlpoUhGyICztl1uRmAmf+wZzraDUcFQVzuQFU6hvV8wBDg/Av6mWOCw+y25AWGoi+ixbLnDmwNeGpxed80ZBuWDWD5Rnn+UpIUWVzxAJvzxoJjgvD7M59oN9SuO77IMBDPQuUMqpuyKoULqNuoYSlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HZRQkOzO; 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="HZRQkOzO" Received: by smtp.kernel.org (Postfix) with ESMTPS id B2DB2C4AF11; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787990930; bh=onwj9ZvmShEMgbw8Rtmke+EWIIMyg7UeYx5VmGnUVLE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HZRQkOzORqqmJdZSI8i5STuzRg6feNkoYejeqiY0clwvoQkzUASNbK6g+NtUVHngI 6ChuSzaQJsa5hC0k8iP4opWf+0AzoXVGZ1PcpttYPVIYC6+dw+2zmlyTc/mQtX+trG m1fEYzkVZFEy5GzryJVs3p+8JMLzKWk4/SfselX9sqjChAfWsx2opi67mRacbzZSzP DNgnY/TXo+jBz1EdNhfjWw5sXR13JUAnycX5f9poiYEfxzc+DmZrcPAjBhYXys3nHN d6kOc9+f+GUiv7S4G6VgTTyX7hsBSM1Ju4G8i7McipMxRrbPLqzKCH+lxvljVnMZQU mXdGUg6C+zGpw== 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 A1CF9C61DCB; Sat, 29 Aug 2026 08:08:50 +0000 (UTC) From: Sven Peter Date: Sat, 29 Aug 2026 10:08:39 +0200 Subject: [PATCH v3 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: <20260829-b4-tbt-fixes-v3-7-e1fab6ac54fe@kernel.org> References: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@kernel.org> In-Reply-To: <20260829-b4-tbt-fixes-v3-0-e1fab6ac54fe@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=onwj9ZvmShEMgbw8Rtmke+EWIIMyg7UeYx5VmGnUVLE=; b=owGbwMvMwCXmIlirolUq95LxtFoSQ9akyf1yXqkpGZY8ob7Hkq3uBrBEfl4X27R/yraL3zvFN 53jyb/YUcrCIMbFICumyLJ9v73pk4dvBJduuvQeZg4rE8gQBi5OAZiIBgPDX9mNd+5vZlhts//y 2xmBSWdupCdc9lh0/m5dkuZsvlus1zgYGa5v4hdhKzVTnh+2+M/ivpn3HCzNznKeeleTOj9k9dS WqxwA 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 c8c648f31107..a1f9dbb66940 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -1407,7 +1407,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 @@ -1432,7 +1432,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); @@ -1479,7 +1479,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); @@ -1530,7 +1530,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); @@ -1596,7 +1596,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); @@ -1667,7 +1667,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); @@ -1676,7 +1676,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); @@ -1685,7 +1685,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); @@ -1784,7 +1784,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)); @@ -2217,7 +2217,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 @@ -2454,7 +2454,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 @@ -2492,7 +2492,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