From patchwork Thu Jun 19 15:24:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 899034 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 265001917CD; Thu, 19 Jun 2025 15:25:07 +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=1750346708; cv=none; b=UeRoU4rseEvJLHqFGrwH6py9pXk0dbLuu3G1TtxA+vfrUsWDAb5z5V26cQ4jv6YJX8nltOBmOujwkHMmWpunQ6Jgt9Ap0cxWi5xzs8YQmR6qp5F8uiop8pfC6TZVYzkG7407QICyjQOnNZcjIfpTTbgXu8hmK5AkUyB03fHHnck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750346708; c=relaxed/simple; bh=QuMCe32n2jXZF4TjVOnNTrne2sMCYVjrFrv05fJ6uWo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=LidFYBVAIb6m4d5MkgNtsm2oDUvU7jxOKI6heOjeMna+hICUoOZ4RdrI1n56IZTq/cV/kuk1SrsCC4JfFLJtN+IEyCwyFZvN1oLLH6C/froXkliwUk+QUdKNqQnZwnxjt242s+/0YhAdplguN3zdipANdCEaeGgINWOG2Zg0ko8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WJC2Vtci; 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="WJC2Vtci" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B06D6C4CEEA; Thu, 19 Jun 2025 15:25:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750346707; bh=QuMCe32n2jXZF4TjVOnNTrne2sMCYVjrFrv05fJ6uWo=; h=From:To:Cc:Subject:Date:From; b=WJC2VtcinPqfIVB8eEXkNXgozwIKAWIE7I36+f81lB5hPhDR16/c7aQ7SBW862f2B coe7n3JLgEMeOfQW1wzNXUcd3NtrXevBI+u6XSaAKGtAmuigjqrVQ2KCQJP1cSqb8q iqVCkwFujfNghpvxZ6eoW4t0735Eqs70znQYvm2vnzNsnhXcT/+43xv8Df8SZgg99k gLxqW11EVcbz6PkFSWvSnLORXUYWxGBmBBfwft8IkHTOz75vv5C3WZiDXcwH624a7A TLr81B09MTcsMRIWTde/gVErl8e3PlTq2TVCwkvCqkIS8JsUE+3OKMHScmdNYD3x9V AOf8icLj738ew== From: Mario Limonciello To: mario.limonciello@amd.com, andreas.noever@gmail.com, michael.jamet@intel.com, westeri@kernel.org, YehezkelShB@gmail.com Cc: stable@vger.kernel.org, Alexander Kovacs , mika.westerberg@linux.intel.com, linux-usb@vger.kernel.org Subject: [PATCH v2] thunderbolt: Fix wake on connect at runtime Date: Thu, 19 Jun 2025 10:24:58 -0500 Message-ID: <20250619152501.697723-1-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello commit 1a760d10ded37 ("thunderbolt: Fix a logic error in wake on connect") fixated on the USB4 port sysfs wakeup file not working properly to control policy, but it had an unintended side effect that the sysfs file controls policy both at runtime and at suspend time. The sysfs file is supposed to only control behavior while system is suspended. Pass whether programming a port for runtime into usb4_switch_set_wake() and if runtime then ignore the value in the sysfs file. Cc: stable@vger.kernel.org Reported-by: Alexander Kovacs Tested-by: Alexander Kovacs Fixes: 1a760d10ded37 ("thunderbolt: Fix a logic error in wake on connect") Signed-off-by: Mario Limonciello --- v2: * Fix kdoc issue reported by lkp robot --- drivers/thunderbolt/switch.c | 8 ++++---- drivers/thunderbolt/tb.h | 2 +- drivers/thunderbolt/usb4.c | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 28febb95f8fa1..e9809fb57c354 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -3437,7 +3437,7 @@ void tb_sw_set_unplugged(struct tb_switch *sw) } } -static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) +static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) { if (flags) tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags); @@ -3445,7 +3445,7 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) tb_sw_dbg(sw, "disabling wakeup\n"); if (tb_switch_is_usb4(sw)) - return usb4_switch_set_wake(sw, flags); + return usb4_switch_set_wake(sw, flags, runtime); return tb_lc_set_wake(sw, flags); } @@ -3521,7 +3521,7 @@ int tb_switch_resume(struct tb_switch *sw, bool runtime) tb_switch_check_wakes(sw); /* Disable wakes */ - tb_switch_set_wake(sw, 0); + tb_switch_set_wake(sw, 0, true); err = tb_switch_tmu_init(sw); if (err) @@ -3603,7 +3603,7 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime) flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; } - tb_switch_set_wake(sw, flags); + tb_switch_set_wake(sw, flags, runtime); if (tb_switch_is_usb4(sw)) usb4_switch_set_sleep(sw); diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 87afd5a7c504b..f503bad864130 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -1317,7 +1317,7 @@ int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size); bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); -int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags); +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime); int usb4_switch_set_sleep(struct tb_switch *sw); int usb4_switch_nvm_sector_size(struct tb_switch *sw); int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index fce3c0f2354a7..d46d9434933c4 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -403,10 +403,11 @@ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) * usb4_switch_set_wake() - Enabled/disable wake * @sw: USB4 router * @flags: Wakeup flags (%0 to disable) + * @runtime: Wake is being programmed during system runtime * * Enables/disables router to wake up from sleep. */ -int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) { struct usb4_port *usb4; struct tb_port *port; @@ -438,13 +439,12 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) val |= PORT_CS_19_WOU4; } else { bool configured = val & PORT_CS_19_PC; + bool wakeup = runtime || device_may_wakeup(&usb4->dev); usb4 = port->usb4; - if (((flags & TB_WAKE_ON_CONNECT) && - device_may_wakeup(&usb4->dev)) && !configured) + if ((flags & TB_WAKE_ON_CONNECT) && wakeup && !configured) val |= PORT_CS_19_WOC; - if (((flags & TB_WAKE_ON_DISCONNECT) && - device_may_wakeup(&usb4->dev)) && configured) + if ((flags & TB_WAKE_ON_DISCONNECT) && wakeup && configured) val |= PORT_CS_19_WOD; if ((flags & TB_WAKE_ON_USB4) && configured) val |= PORT_CS_19_WOU4;