On Mon, Mar 03, 2025 at 06:33:06AM -0800, Kenneth Crudup wrote: > > On 3/3/25 06:20, Mika Westerberg wrote: > > > Actually just managed to reproduce this with hibernate \o/ so debugging > > now. > > OK, this is good ... but now you've got me wondering if I indeed saw it > during suspend cycles as well (I usually suspend only, then systemd will > initiate a hibernation after 4H so just going back/forth to the office > shouldn't trigger this). > > Waiting to see what you find, Okay, I think I figured out what is going on. Indeed d6d458d4 is buggy but not the way I thought it was ;-) What actually happens is that once we resume from hibernate we discover the tunnels created by the boot kernel and tear them down. For discovery we never start the DPRX negotiation but we still ended up calling tb_dp_dprx_stop() which does tb_tunnel_put() and this releases the tunnel object. All accesses after this and up touching already freed memory! I've played with the below patch for a while and I have not seen that issue anymore. Can you try it out on your end too? diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 8229a6fbda5a..717b31d78728 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1009,6 +1009,8 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunnel) */ tb_tunnel_get(tunnel); + tunnel->dprx_started = true; + if (tunnel->callback) { tunnel->dprx_timeout = dprx_timeout_to_ktime(dprx_timeout); queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0); @@ -1021,9 +1023,12 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunnel) static void tb_dp_dprx_stop(struct tb_tunnel *tunnel) { - tunnel->dprx_canceled = true; - cancel_delayed_work(&tunnel->dprx_work); - tb_tunnel_put(tunnel); + if (tunnel->dprx_started) { + tunnel->dprx_started = false; + tunnel->dprx_canceled = true; + cancel_delayed_work(&tunnel->dprx_work); + tb_tunnel_put(tunnel); + } } static int tb_dp_activate(struct tb_tunnel *tunnel, bool active) diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 7f6d3a18a41e..8a0a0cb21a89 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -63,6 +63,7 @@ enum tb_tunnel_state { * @allocated_down: Allocated downstream bandwidth (only for USB3) * @bw_mode: DP bandwidth allocation mode registers can be used to * determine consumed and allocated bandwidth + * @dprx_started: DPRX negotiation was started (tb_dp_dprx_start() was called for it) * @dprx_canceled: Was DPRX capabilities read poll canceled * @dprx_timeout: If set DPRX capabilities read poll work will timeout after this passes * @dprx_work: Worker that is scheduled to poll completion of DPRX capabilities read @@ -100,6 +101,7 @@ struct tb_tunnel { int allocated_up; int allocated_down; bool bw_mode; + bool dprx_started; bool dprx_canceled; ktime_t dprx_timeout; struct delayed_work dprx_work;