From patchwork Wed Aug 19 11:58:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258829 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8BD4BC433E3 for ; Wed, 19 Aug 2020 12:03:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 629E820866 for ; Wed, 19 Aug 2020 12:03:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727987AbgHSMDg (ORCPT ); Wed, 19 Aug 2020 08:03:36 -0400 Received: from mga17.intel.com ([192.55.52.151]:31803 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728111AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: ++V/PbRKPi+sYaTeZCpv7lbt0fe87fo50vjto7d6fQf0NXP2JHQ4WP01OGEiNaz0pdMO0clFf6 Hco9ZpdwWecw== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="135160287" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="135160287" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:10 -0700 IronPort-SDR: GSOtgI+uUpHX3Tbz0J8kb0LlqOieTjLHeeC4RbNBE0a9NYzylazaeO118rb9CzjVzxPtNMORqp Vmp1SmZXPxSA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="336938682" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga007.jf.intel.com with ESMTP; 19 Aug 2020 04:59:07 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 54887B8; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 01/19] thunderbolt: Optimize Force Power logic Date: Wed, 19 Aug 2020 14:58:47 +0300 Message-Id: <20200819115905.59834-2-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: Rajmohan Mani Currently the "Force Power" logic uses 10 retries, each with a delay of 250 ms. Thunderbolt controllers in Ice Lake and Tiger Lake platforms are found to complete this in the order of 3 ms or so. Since this delay is in resume path, surplus delay is effectively affecting runtime PM resume flows. Decrease the granularity of the delay to 3 ms and increase the number of retries so we wait maximum of ~1 s which is the recommended timeout. This should make runtime resume a bit faster. Reported-by: Dana Alkattan Signed-off-by: Rajmohan Mani Signed-off-by: Mika Westerberg --- drivers/thunderbolt/nhi_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thunderbolt/nhi_ops.c b/drivers/thunderbolt/nhi_ops.c index 6795851aac95..c0d5ccbb10f5 100644 --- a/drivers/thunderbolt/nhi_ops.c +++ b/drivers/thunderbolt/nhi_ops.c @@ -59,7 +59,7 @@ static int icl_nhi_force_power(struct tb_nhi *nhi, bool power) pci_write_config_dword(nhi->pdev, VS_CAP_22, vs_cap); if (power) { - unsigned int retries = 10; + unsigned int retries = 350; u32 val; /* Wait until the firmware tells it is up and running */ @@ -67,7 +67,7 @@ static int icl_nhi_force_power(struct tb_nhi *nhi, bool power) pci_read_config_dword(nhi->pdev, VS_CAP_9, &val); if (val & VS_CAP_9_FW_READY) return 0; - msleep(250); + usleep_range(3000, 3100); } while (--retries); return -ETIMEDOUT; From patchwork Wed Aug 19 11:58:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258836 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 98C02C433E4 for ; Wed, 19 Aug 2020 11:59:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 81CB82075E for ; Wed, 19 Aug 2020 11:59:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728489AbgHSL7V (ORCPT ); Wed, 19 Aug 2020 07:59:21 -0400 Received: from mga17.intel.com ([192.55.52.151]:31803 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728324AbgHSL7N (ORCPT ); Wed, 19 Aug 2020 07:59:13 -0400 IronPort-SDR: yHw3ZwBnEmCkLaPo/LX8AVe2sU/KdiWDAkGCaK8dS2YGBHNPEus8HfCkVYsyjJi1bVmgN0TOpM SvFxakRfr+YA== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="135160284" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="135160284" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:10 -0700 IronPort-SDR: nxi/5AY/23BGtTBP5/pHeITqLiRkcnCFR+WljHGgHaq95cDGgK+GQ2RtjcVvqXw47tF8sWQAWo kqq06Rwa5Szg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="497212550" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga006.fm.intel.com with ESMTP; 19 Aug 2020 04:59:07 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 5A4C326A; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 02/19] thunderbolt: Optimize NHI LC mailbox command processing Date: Wed, 19 Aug 2020 14:58:48 +0300 Message-Id: <20200819115905.59834-3-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: Rajmohan Mani Currently the Ice Lake and Tiger Lake NHI (host controller) LC (link controller) mailbox command processing checks for the completion of command every 100 msecs. These controllers are found to complete this in the order of 1 ms or so. Since this delay is in suspend path, surplus delay is effectively affecting runtime PM suspend flows. Optimize this so that we do the wait for 1 ms after reading the mailbox register. This should make Ice Lake and Tiger Lake runtime suspend take less time to complete. Reported-by: Dana Alkattan Signed-off-by: Rajmohan Mani Signed-off-by: Mika Westerberg --- drivers/thunderbolt/nhi_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thunderbolt/nhi_ops.c b/drivers/thunderbolt/nhi_ops.c index c0d5ccbb10f5..28583f9faf46 100644 --- a/drivers/thunderbolt/nhi_ops.c +++ b/drivers/thunderbolt/nhi_ops.c @@ -97,7 +97,7 @@ static int icl_nhi_lc_mailbox_cmd_complete(struct tb_nhi *nhi, int timeout) pci_read_config_dword(nhi->pdev, VS_CAP_18, &data); if (data & VS_CAP_18_DONE) goto clear; - msleep(100); + usleep_range(1000, 1100); } while (time_before(jiffies, end)); return -ETIMEDOUT; From patchwork Wed Aug 19 11:58:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258834 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90622C433DF for ; Wed, 19 Aug 2020 12:00:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 77A32205CB for ; Wed, 19 Aug 2020 12:00:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728295AbgHSMA2 (ORCPT ); Wed, 19 Aug 2020 08:00:28 -0400 Received: from mga02.intel.com ([134.134.136.20]:1227 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728412AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: q9ccMLz+IN8zcluDn/ngIDYv3RgBrWlySZLIuANlmt4aTt3qUDI8XzLhffGQ6W0SvwwQN6SOD7 uRKOeg0SVTMg== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="142904872" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="142904872" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:14 -0700 IronPort-SDR: PpzLTw4aqqPu8zna03CGkb69bCaPxR9U+8TtLKzKzB/zNpD+XQlUHtZdXYMZiIcR6kRpn1Cmou Ik7DN8K1GqLQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="497724277" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga005.fm.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 7FB7B377; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 05/19] thunderbolt: Do not program NFC buffers for USB4 router protocol adapters Date: Wed, 19 Aug 2020 14:58:51 +0300 Message-Id: <20200819115905.59834-6-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org USB4 spec says that NFC buffers field is not used for protocol adapters, only for lane adapters so make tb_port_add_nfc_credits() skip non-lane adapters in order to follow the spec. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 698c52775eec..72756c8ceead 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -601,6 +601,13 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits) if (credits == 0 || port->sw->is_unplugged) return 0; + /* + * USB4 restricts programming NFC buffers to lane adapters only + * so skip other ports. + */ + if (tb_switch_is_usb4(port->sw) && !tb_port_is_null(port)) + return 0; + nfc_credits = port->config.nfc_credits & ADP_CS_4_NFC_BUFFERS_MASK; nfc_credits += credits; From patchwork Wed Aug 19 11:58:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3879BC433E1 for ; Wed, 19 Aug 2020 12:00:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1658A207BB for ; Wed, 19 Aug 2020 12:00:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728368AbgHSL7f (ORCPT ); Wed, 19 Aug 2020 07:59:35 -0400 Received: from mga05.intel.com ([192.55.52.43]:49550 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728409AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: Xm7ZGRSNj94zajWBfKi4BIzHJdynwp7wB/+rlRNW5GwM8Da2AACoGquuDQ+HPbOHpizpKc8weX /hICI7GRNa/g== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922667" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922667" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:14 -0700 IronPort-SDR: +wZIaCmcceJ/nNxrZd5PHt1REUyEaecsb4eqtyJOril7LjqKk9j8IdkSWu9cJeQ7hMHKIFHDh0 TAOVRmQggITw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310755" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga002.fm.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id A1A3E463; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 08/19] thunderbolt: Tear down DP tunnels when suspending Date: Wed, 19 Aug 2020 14:58:54 +0300 Message-Id: <20200819115905.59834-9-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org DP tunnels do not need the same kind of treatment as others because they are created based on hot-plug events on DP adapter ports, and the display stack does not need the tunnels to be enabled when resuming from suspend. Also Tiger Lake Thunderbolt controller sends unplug event on D3 exit so this avoids that as well. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index a6da2d0567ae..c35d5fec48f4 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -910,6 +910,29 @@ static void tb_dp_resource_available(struct tb *tb, struct tb_port *port) tb_tunnel_dp(tb); } +static void tb_disconnect_and_release_dp(struct tb *tb) +{ + struct tb_cm *tcm = tb_priv(tb); + struct tb_tunnel *tunnel, *n; + + /* + * Tear down all DP tunnels and release their resources. They + * will be re-established after resume based on plug events. + */ + list_for_each_entry_safe_reverse(tunnel, n, &tcm->tunnel_list, list) { + if (tb_tunnel_is_dp(tunnel)) + tb_deactivate_and_free_tunnel(tunnel); + } + + while (!list_empty(&tcm->dp_resources)) { + struct tb_port *port; + + port = list_first_entry(&tcm->dp_resources, + struct tb_port, list); + list_del_init(&port->list); + } +} + static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) { struct tb_port *up, *down, *port; @@ -1226,6 +1249,7 @@ static int tb_suspend_noirq(struct tb *tb) struct tb_cm *tcm = tb_priv(tb); tb_dbg(tb, "suspending...\n"); + tb_disconnect_and_release_dp(tb); tb_switch_suspend(tb->root_switch); tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */ tb_dbg(tb, "suspend finished\n"); From patchwork Wed Aug 19 11:58:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258828 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9CFFCC433DF for ; Wed, 19 Aug 2020 12:03:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6E0C1205CB for ; Wed, 19 Aug 2020 12:03:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727856AbgHSMDV (ORCPT ); Wed, 19 Aug 2020 08:03:21 -0400 Received: from mga07.intel.com ([134.134.136.100]:61774 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728465AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: jWqWtX1glcMnSJJ+x6+dkeC0kkEzU1DeOtQm7yUGgAK9N9EUJEqO6YdtAnDW4uoi8tGXDGktZ/ kBDbyX7wN6uw== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="219396076" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="219396076" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:14 -0700 IronPort-SDR: NnJVoq61uZ6zB5jh7Tf8h7wkIB9R7RwR0g82aNCd5/IlM59m4U/UsSF+9IZKVPjAFCXvwDHBHm ISHXAHtIQsMA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="327067238" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga008.jf.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id AAB20467; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 09/19] thunderbolt: Initialize TMU again on resume Date: Wed, 19 Aug 2020 14:58:55 +0300 Message-Id: <20200819115905.59834-10-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The TMU will be reset after router exits sleep so in order to re-configure it upon resume make sure the structure is initialized again based on the current hardware state. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index fb30ea1dfc31..de186d6ed166 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2534,6 +2534,10 @@ int tb_switch_resume(struct tb_switch *sw) if (err) return err; + err = tb_switch_tmu_init(sw); + if (err) + return err; + /* check for surviving downstream switches */ tb_switch_for_each_port(sw, port) { if (!tb_port_has_remote(port) && !port->xdomain) From patchwork Wed Aug 19 11:58:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258832 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D846AC433E1 for ; Wed, 19 Aug 2020 12:02:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BE1A2206DA for ; Wed, 19 Aug 2020 12:02:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728498AbgHSL7a (ORCPT ); Wed, 19 Aug 2020 07:59:30 -0400 Received: from mga12.intel.com ([192.55.52.136]:34066 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728260AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: nPUFkw7LkQSai0008UOMKf/u0xR75ptVtUYjmqHIy31wwoGQVpKMPxzr7DtYzPdGyACHJTX+70 tpLdGOQ/3Emg== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="134610557" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="134610557" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:16 -0700 IronPort-SDR: 88rLKxKPvltUAIjZMepMWjQj1Zn9zhGaGdv708Itao6hFHG5ypSgQ+dBruBfeHbg/7YAdrafFR jLY4mFyCizbw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="472211902" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga005.jf.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id BC68951B; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 11/19] thunderbolt: Configure link after lane bonding is enabled Date: Wed, 19 Aug 2020 14:58:57 +0300 Message-Id: <20200819115905.59834-12-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org During testing it was noticed that the link is not properly restored after the domain exits sleep if the link configured bits are set before lane bonding is enabled. The USB4 spec does not say in which order these need to be set but setting link configured afterwards makes the link restoration work so we do that instead. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/lc.c | 6 ---- drivers/thunderbolt/switch.c | 55 +++++++++++++++++++++++++++--------- drivers/thunderbolt/tb.c | 5 ++++ drivers/thunderbolt/tb.h | 2 ++ drivers/thunderbolt/usb4.c | 6 ---- 5 files changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index 19be627d090f..b2f62ba0421d 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -94,9 +94,6 @@ int tb_lc_configure_link(struct tb_switch *sw) struct tb_port *up, *down; int ret; - if (!tb_route(sw) || tb_switch_is_icm(sw)) - return 0; - up = tb_upstream_port(sw); down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); @@ -124,9 +121,6 @@ void tb_lc_unconfigure_link(struct tb_switch *sw) { struct tb_port *up, *down; - if (sw->is_unplugged || !tb_route(sw) || tb_switch_is_icm(sw)) - return; - up = tb_upstream_port(sw); down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index e1ba8215144b..ecc47ea81bb6 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2012,10 +2012,6 @@ int tb_switch_configure(struct tb_switch *sw) return ret; ret = usb4_switch_setup(sw); - if (ret) - return ret; - - ret = usb4_switch_configure_link(sw); } else { if (sw->config.vendor_id != PCI_VENDOR_ID_INTEL) tb_sw_warn(sw, "unknown switch vendor id %#x\n", @@ -2029,10 +2025,6 @@ int tb_switch_configure(struct tb_switch *sw) /* Enumerate the switch */ ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH, ROUTER_CS_1, 3); - if (ret) - return ret; - - ret = tb_lc_configure_link(sw); } if (ret) return ret; @@ -2315,6 +2307,48 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) tb_sw_dbg(sw, "lane bonding disabled\n"); } +/** + * tb_switch_configure_link() - Set link configured + * @sw: Switch whose link is configured + * + * Sets the link upstream from @sw configured (from both ends) so that + * it will not be disconnected when the domain exits sleep. Can be + * called for any switch. + * + * It is recommended that this is called after lane bonding is enabled. + * + * Returns %0 on success and negative errno in case of error. + */ +int tb_switch_configure_link(struct tb_switch *sw) +{ + if (!tb_route(sw) || tb_switch_is_icm(sw)) + return 0; + + if (tb_switch_is_usb4(sw)) + return usb4_switch_configure_link(sw); + return tb_lc_configure_link(sw); +} + +/** + * tb_switch_unconfigure_link() - Unconfigure link + * @sw: Switch whose link is unconfigured + * + * Sets the link unconfigured so the @sw will be disconnected if the + * domain exists sleep. + */ +void tb_switch_unconfigure_link(struct tb_switch *sw) +{ + if (sw->is_unplugged) + return; + if (!tb_route(sw) || tb_switch_is_icm(sw)) + return; + + if (tb_switch_is_usb4(sw)) + usb4_switch_unconfigure_link(sw); + else + tb_lc_unconfigure_link(sw); +} + /** * tb_switch_add() - Add a switch to the domain * @sw: Switch to add @@ -2449,11 +2483,6 @@ void tb_switch_remove(struct tb_switch *sw) if (!sw->is_unplugged) tb_plug_events_active(sw, false); - if (tb_switch_is_usb4(sw)) - usb4_switch_unconfigure_link(sw); - else - tb_lc_unconfigure_link(sw); - tb_switch_nvm_remove(sw); if (tb_route(sw)) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index c35d5fec48f4..54a4daf0b1b4 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -593,6 +593,8 @@ static void tb_scan_port(struct tb_port *port) /* Enable lane bonding if supported */ tb_switch_lane_bonding_enable(sw); + /* Set the link configured */ + tb_switch_configure_link(sw); if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to enable TMU\n"); @@ -681,6 +683,7 @@ static void tb_free_unplugged_children(struct tb_switch *sw) if (port->remote->sw->is_unplugged) { tb_retimer_remove_all(port); tb_remove_dp_resources(port->remote->sw); + tb_switch_unconfigure_link(port->remote->sw); tb_switch_lane_bonding_disable(port->remote->sw); tb_switch_remove(port->remote->sw); port->remote = NULL; @@ -1076,6 +1079,7 @@ static void tb_handle_hotplug(struct work_struct *work) tb_free_invalid_tunnels(tb); tb_remove_dp_resources(port->remote->sw); tb_switch_tmu_disable(port->remote->sw); + tb_switch_unconfigure_link(port->remote->sw); tb_switch_lane_bonding_disable(port->remote->sw); tb_switch_remove(port->remote->sw); port->remote = NULL; @@ -1269,6 +1273,7 @@ static void tb_restore_children(struct tb_switch *sw) continue; tb_switch_lane_bonding_enable(port->remote->sw); + tb_switch_configure_link(port->remote->sw); tb_restore_children(port->remote->sw); } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 69e78bbed53a..dcdc886412f5 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -767,6 +767,8 @@ static inline bool tb_switch_is_icm(const struct tb_switch *sw) int tb_switch_lane_bonding_enable(struct tb_switch *sw); void tb_switch_lane_bonding_disable(struct tb_switch *sw); +int tb_switch_configure_link(struct tb_switch *sw); +void tb_switch_unconfigure_link(struct tb_switch *sw); bool tb_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in); int tb_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in); diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 2b8355e6b65f..dd601a6db23c 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -368,9 +368,6 @@ int usb4_switch_configure_link(struct tb_switch *sw) { struct tb_port *up; - if (!tb_route(sw)) - return 0; - up = tb_upstream_port(sw); return usb4_set_port_configured(up, true); } @@ -385,9 +382,6 @@ void usb4_switch_unconfigure_link(struct tb_switch *sw) { struct tb_port *up; - if (sw->is_unplugged || !tb_route(sw)) - return; - up = tb_upstream_port(sw); usb4_set_port_configured(up, false); } From patchwork Wed Aug 19 11:59:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258831 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F534C433E1 for ; Wed, 19 Aug 2020 12:03:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C9BFD205CB for ; Wed, 19 Aug 2020 12:03:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728387AbgHSMDA (ORCPT ); Wed, 19 Aug 2020 08:03:00 -0400 Received: from mga02.intel.com ([134.134.136.20]:1231 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728343AbgHSL7S (ORCPT ); Wed, 19 Aug 2020 07:59:18 -0400 IronPort-SDR: 955j5xxPleaA/SpgKVSnTiaDJV6bO5wyFX8DMphM4qlWlcEFK/gtpF7kjTGn1rBpwxO0cJ8yTr 2Oo3eYMTcvxA== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="142904887" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="142904887" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:18 -0700 IronPort-SDR: 0GjM+kqIFOcDe/ndho/BZ1LQSxXoS5IIuNRg6nF6w3KYz56ZVoDDWZQOgFFx3yDOjUGD4pWegi VEMNlHf7kSaA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="497724282" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga005.fm.intel.com with ESMTP; 19 Aug 2020 04:59:14 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id E0B656E8; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 15/19] thunderbolt: Enable wakes from system suspend Date: Wed, 19 Aug 2020 14:59:01 +0300 Message-Id: <20200819115905.59834-16-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org In order for the router and the whole domain to wake up from system suspend states we need to enable wakes for the connected routers. For device routers we enable wakes from PCIe and USB 3.x. This allows devices such as keyboards connected to USB 3.x hub that is tunneled to wake the system up as expected. For all routers we enabled wake on USB4 for each connected ports. This is used to propagate the wake from router to another. Do the same for legacy routers through link controller vendor specific registers as documented in USB4 spec chapter 13. While there correct kernel-doc of usb4_switch_set_sleep() -- it does not enable wakes instead there is a separate function (usb4_switch_set_wake()) that does. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/domain.c | 2 + drivers/thunderbolt/lc.c | 67 ++++++++++++++++++++ drivers/thunderbolt/nhi.c | 2 + drivers/thunderbolt/switch.c | 30 ++++++++- drivers/thunderbolt/tb.h | 9 +++ drivers/thunderbolt/tb_regs.h | 12 ++++ drivers/thunderbolt/usb4.c | 112 +++++++++++++++++++++++++++++++++- 7 files changed, 231 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index bba4cbfa9759..7ca6a2b34ddc 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -455,6 +455,8 @@ int tb_domain_add(struct tb *tb) /* This starts event processing */ mutex_unlock(&tb->lock); + device_init_wakeup(&tb->dev, true); + pm_runtime_no_callbacks(&tb->dev); pm_runtime_set_active(&tb->dev); pm_runtime_enable(&tb->dev); diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index 44647fa1ec1c..41e6c738f6c8 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -158,6 +158,73 @@ void tb_lc_unconfigure_xdomain(struct tb_port *port) tb_lc_set_xdomain_configured(port, false); } +static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, + unsigned int flags) +{ + u32 ctrl; + int ret; + + /* + * Enable wake on PCIe and USB4 (wake coming from another + * router). + */ + ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, + offset + TB_LC_SX_CTRL, 1); + if (ret) + return ret; + + ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WOP | + TB_LC_SX_CTRL_WOU4); + + if (flags & TB_WAKE_ON_CONNECT) + ctrl |= TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD; + if (flags & TB_WAKE_ON_USB4) + ctrl |= TB_LC_SX_CTRL_WOU4; + if (flags & TB_WAKE_ON_PCIE) + ctrl |= TB_LC_SX_CTRL_WOP; + + return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, offset + TB_LC_SX_CTRL, 1); +} + +/** + * tb_lc_set_wake() - Enable/disable wake + * @sw: Switch whose wakes to configure + * @flags: Wakeup flags (%0 to disable) + * + * For each LC sets wake bits accordingly. + */ +int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags) +{ + int start, size, nlc, ret, i; + u32 desc; + + if (sw->generation < 2) + return 0; + + if (!tb_route(sw)) + return 0; + + ret = read_lc_desc(sw, &desc); + if (ret) + return ret; + + /* Figure out number of link controllers */ + nlc = desc & TB_LC_DESC_NLC_MASK; + start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT; + size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT; + + /* For each link controller set sleep bit */ + for (i = 0; i < nlc; i++) { + unsigned int offset = sw->cap_lc + start + i * size; + + ret = tb_lc_set_wake_one(sw, offset, flags); + if (ret) + return ret; + } + + return 0; +} + /** * tb_lc_set_sleep() - Inform LC that the switch is going to sleep * @sw: Switch to set sleep diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 5f7489fa1327..24d2b7eff59b 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -1157,6 +1157,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_drvdata(pdev, tb); + device_wakeup_enable(&pdev->dev); + pm_runtime_allow(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, TB_AUTOSUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index a8df25dae57b..a2ebf51ac389 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2036,7 +2036,7 @@ int tb_switch_configure(struct tb_switch *sw) route = tb_route(sw); tb_dbg(tb, "%s Switch at %#llx (depth: %d, up port: %d)\n", - sw->config.enabled ? "restoring " : "initializing", route, + sw->config.enabled ? "restoring" : "initializing", route, tb_route_length(route), sw->config.upstream_port_number); sw->config.enabled = 1; @@ -2502,6 +2502,13 @@ int tb_switch_add(struct tb_switch *sw) return ret; } + /* + * Thunderbolt routers do not generate wakeups themselves but + * they forward wakeups from tunneled protocols, so enable it + * here. + */ + device_init_wakeup(&sw->dev, true); + pm_runtime_set_active(&sw->dev); if (sw->rpm) { pm_runtime_set_autosuspend_delay(&sw->dev, TB_AUTOSUSPEND_DELAY); @@ -2579,6 +2586,18 @@ void tb_sw_set_unplugged(struct tb_switch *sw) } } +static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) +{ + if (flags) + tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags); + else + tb_sw_dbg(sw, "disabling wakeup\n"); + + if (tb_switch_is_usb4(sw)) + return usb4_switch_set_wake(sw, flags); + return tb_lc_set_wake(sw, flags); +} + int tb_switch_resume(struct tb_switch *sw) { struct tb_port *port; @@ -2624,6 +2643,9 @@ int tb_switch_resume(struct tb_switch *sw) if (err) return err; + /* Disable wakes */ + tb_switch_set_wake(sw, 0); + err = tb_switch_tmu_init(sw); if (err) return err; @@ -2659,6 +2681,7 @@ int tb_switch_resume(struct tb_switch *sw) void tb_switch_suspend(struct tb_switch *sw) { + unsigned int flags = 0; struct tb_port *port; int err; @@ -2671,6 +2694,11 @@ void tb_switch_suspend(struct tb_switch *sw) tb_switch_suspend(port->remote->sw); } + if (device_may_wakeup(&sw->dev)) + flags = TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; + + tb_switch_set_wake(sw, flags); + if (tb_switch_is_usb4(sw)) usb4_switch_set_sleep(sw); else diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index f58cd3fa98ea..847accd91bfa 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -333,6 +333,13 @@ struct tb_path { */ #define TB_PATH_MAX_HOPS (7 * 2) +/* Possible wake types */ +#define TB_WAKE_ON_CONNECT BIT(0) +#define TB_WAKE_ON_DISCONNECT BIT(1) +#define TB_WAKE_ON_USB4 BIT(2) +#define TB_WAKE_ON_USB3 BIT(3) +#define TB_WAKE_ON_PCIE BIT(4) + /** * struct tb_cm_ops - Connection manager specific operations vector * @driver_ready: Called right after control channel is started. Used by @@ -852,6 +859,7 @@ int tb_lc_configure_port(struct tb_port *port); void tb_lc_unconfigure_port(struct tb_port *port); int tb_lc_configure_xdomain(struct tb_port *port); void tb_lc_unconfigure_xdomain(struct tb_port *port); +int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags); int tb_lc_set_sleep(struct tb_switch *sw); bool tb_lc_lane_bonding_possible(struct tb_switch *sw); bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in); @@ -907,6 +915,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_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/tb_regs.h b/drivers/thunderbolt/tb_regs.h index d1a40baa63d2..0431e415e3bc 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -178,6 +178,8 @@ struct tb_regs_switch_header { #define ROUTER_CS_4 0x04 #define ROUTER_CS_5 0x05 #define ROUTER_CS_5_SLP BIT(0) +#define ROUTER_CS_5_WOP BIT(1) +#define ROUTER_CS_5_WOU BIT(2) #define ROUTER_CS_5_C3S BIT(23) #define ROUTER_CS_5_PTO BIT(24) #define ROUTER_CS_5_UTO BIT(25) @@ -186,6 +188,8 @@ struct tb_regs_switch_header { #define ROUTER_CS_6 0x06 #define ROUTER_CS_6_SLPR BIT(0) #define ROUTER_CS_6_TNS BIT(1) +#define ROUTER_CS_6_WOPS BIT(2) +#define ROUTER_CS_6_WOUS BIT(3) #define ROUTER_CS_6_HCI BIT(18) #define ROUTER_CS_6_CR BIT(25) #define ROUTER_CS_7 0x07 @@ -302,9 +306,13 @@ struct tb_regs_port_header { #define PORT_CS_18 0x12 #define PORT_CS_18_BE BIT(8) #define PORT_CS_18_TCM BIT(9) +#define PORT_CS_18_WOU4S BIT(18) #define PORT_CS_19 0x13 #define PORT_CS_19_PC BIT(3) #define PORT_CS_19_PID BIT(4) +#define PORT_CS_19_WOC BIT(16) +#define PORT_CS_19_WOD BIT(17) +#define PORT_CS_19_WOU4 BIT(18) /* Display Port adapter registers */ #define ADP_DP_CS_0 0x00 @@ -418,6 +426,10 @@ struct tb_regs_hop { #define TB_LC_PORT_ATTR_BE BIT(12) #define TB_LC_SX_CTRL 0x96 +#define TB_LC_SX_CTRL_WOC BIT(1) +#define TB_LC_SX_CTRL_WOD BIT(2) +#define TB_LC_SX_CTRL_WOU4 BIT(5) +#define TB_LC_SX_CTRL_WOP BIT(6) #define TB_LC_SX_CTRL_L1C BIT(16) #define TB_LC_SX_CTRL_L1D BIT(17) #define TB_LC_SX_CTRL_L2C BIT(20) diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 59b8b51d1fa4..40f13579a3fe 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -196,6 +196,46 @@ static int usb4_switch_op(struct tb_switch *sw, u16 opcode, u8 *status) return 0; } +static void usb4_switch_check_wakes(struct tb_switch *sw) +{ + struct tb_port *port; + bool wakeup = false; + u32 val; + + if (!device_may_wakeup(&sw->dev)) + return; + + if (tb_route(sw)) { + if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1)) + return; + + tb_sw_dbg(sw, "PCIe wake: %s, USB3 wake: %s\n", + (val & ROUTER_CS_6_WOPS) ? "yes" : "no", + (val & ROUTER_CS_6_WOUS) ? "yes" : "no"); + + wakeup = val & (ROUTER_CS_6_WOPS | ROUTER_CS_6_WOUS); + } + + /* Check for any connected downstream ports for USB4 wake */ + tb_switch_for_each_port(sw, port) { + if (!tb_port_has_remote(port)) + continue; + + if (tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_18, 1)) + break; + + tb_port_dbg(port, "USB4 wake: %s\n", + (val & PORT_CS_18_WOU4S) ? "yes" : "no"); + + if (val & PORT_CS_18_WOU4S) + wakeup = true; + } + + if (wakeup) + pm_wakeup_event(&sw->dev, 0); +} + static bool link_is_usb4(struct tb_port *port) { u32 val; @@ -229,6 +269,8 @@ int usb4_switch_setup(struct tb_switch *sw) u32 val = 0; int ret; + usb4_switch_check_wakes(sw); + if (!tb_route(sw)) return 0; @@ -359,12 +401,78 @@ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) return !!(val & PORT_CS_18_BE); } +/** + * usb4_switch_set_wake() - Enabled/disable wake + * @sw: USB4 router + * @flags: Wakeup flags (%0 to disable) + * + * Enables/disables router to wake up from sleep. + */ +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) +{ + struct tb_port *port; + u64 route = tb_route(sw); + u32 val; + int ret; + + /* + * Enable wakes coming from all USB4 downstream ports (from + * child routers). For device routers do this also for the + * upstream USB4 port. + */ + tb_switch_for_each_port(sw, port) { + if (!route && tb_is_upstream_port(port)) + continue; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val &= ~(PORT_CS_19_WOC | PORT_CS_19_WOD | PORT_CS_19_WOU4); + + if (flags & TB_WAKE_ON_CONNECT) + val |= PORT_CS_19_WOC; + if (flags & TB_WAKE_ON_DISCONNECT) + val |= PORT_CS_19_WOD; + if (flags & TB_WAKE_ON_USB4) + val |= PORT_CS_19_WOU4; + + ret = tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + } + + /* + * Enable wakes from PCIe and USB 3.x on this router. Only + * needed for device routers. + */ + if (route) { + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); + if (ret) + return ret; + + val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU); + if (flags & TB_WAKE_ON_USB3) + val |= ROUTER_CS_5_WOU; + if (flags & TB_WAKE_ON_PCIE) + val |= ROUTER_CS_5_WOP; + + ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); + if (ret) + return ret; + } + + return 0; +} + /** * usb4_switch_set_sleep() - Prepare the router to enter sleep * @sw: USB4 router * - * Enables wakes and sets sleep bit for the router. Returns when the - * router sleep ready bit has been asserted. + * Sets sleep bit for the router. Returns when the router sleep ready + * bit has been asserted. */ int usb4_switch_set_sleep(struct tb_switch *sw) { From patchwork Wed Aug 19 11:59:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258833 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3059C433EA for ; Wed, 19 Aug 2020 12:01:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 99D17207BB for ; Wed, 19 Aug 2020 12:01:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728169AbgHSMBc (ORCPT ); Wed, 19 Aug 2020 08:01:32 -0400 Received: from mga05.intel.com ([192.55.52.43]:49550 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728021AbgHSL74 (ORCPT ); Wed, 19 Aug 2020 07:59:56 -0400 IronPort-SDR: wIxPof3BWspEKl2Cm1ww3To8qucSLttq8oVQI+DVAs2ad+tEUw8KmKd3X8P5n7wA6WDZufaOeD 0rXPfVNl6tDw== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922678" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922678" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:17 -0700 IronPort-SDR: iWifSpr83vxu9j5doJ0hUGI4lOCtt6pV6KNeBswt6aumKvXT64PSjYZ5Ao9kXVI0pHR36ErZ+J rvebvyz7CrkA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310787" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga002.fm.intel.com with ESMTP; 19 Aug 2020 04:59:14 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id F31EB790; Wed, 19 Aug 2020 14:59:06 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 17/19] ACPI: Export acpi_get_first_physical_node() to modules Date: Wed, 19 Aug 2020 14:59:03 +0300 Message-Id: <20200819115905.59834-18-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This function will be needed by the Thunderbolt driver when it parses ACPI description for linking tunneled ports to the Thunderbolt controller device. Cc: Rafael J. Wysocki Signed-off-by: Mika Westerberg --- drivers/acpi/bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 54002670cb7a..53cc1e0cef21 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -551,6 +551,7 @@ struct device *acpi_get_first_physical_node(struct acpi_device *adev) mutex_unlock(physical_node_lock); return phys_dev; } +EXPORT_SYMBOL_GPL(acpi_get_first_physical_node); static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev, const struct device *dev) From patchwork Wed Aug 19 11:59:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 258830 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41349C433DF for ; Wed, 19 Aug 2020 12:03:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 18257205CB for ; Wed, 19 Aug 2020 12:03:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728133AbgHSMCm (ORCPT ); Wed, 19 Aug 2020 08:02:42 -0400 Received: from mga17.intel.com ([192.55.52.151]:31808 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728207AbgHSL7X (ORCPT ); Wed, 19 Aug 2020 07:59:23 -0400 IronPort-SDR: sllUySao0ywIFGadz6FChHZ5kXMZ1jlEoYJ3CXav293cTSsiOLhp7NguaCLg7rwhDaXo1PINc2 yeIt0AnqYgqw== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="135160298" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="135160298" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:18 -0700 IronPort-SDR: I3mHLQ458sXJ0BmYOldWmReT6cu6jLc8dWFPPmytU/IVfDO5Txqt/4xqIVVqL59Ae4TeKNhd5G rbNr1Ov53rHQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="336938694" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga007.jf.intel.com with ESMTP; 19 Aug 2020 04:59:14 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 07C2F7C5; Wed, 19 Aug 2020 14:59:07 +0300 (EEST) From: Mika Westerberg To: linux-usb@vger.kernel.org Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , Andreas Noever , Rajmohan Mani , Dana Alkattan , Lukas Wunner , "Rafael J . Wysocki" , Bjorn Helgaas , Len Brown , Greg Kroah-Hartman , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH 18/19] thunderbolt: Create device links from ACPI description Date: Wed, 19 Aug 2020 14:59:04 +0300 Message-Id: <20200819115905.59834-19-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200819115905.59834-1-mika.westerberg@linux.intel.com> References: <20200819115905.59834-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The new way to describe relationship between tunneled ports and USB4 NHI (Native Host Interface) is with ACPI _DSD looking like below for a PCIe downstream port: Scope (\_SB.PCI0) { Device (NHI0) { } // Thunderbolt NHI Device (DSB0) // Hotplug downstream port { Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () {"usb4-host-interface", \_SB.PCI0.NHI0}, ... } }) } } This is "documented" in these [1] USB-IF slides and being used on systems that ship with Windows. The _DSD can be added to tunneled USB3 and PCIe ports, and is needed to make sure the USB4 NHI is resumed before any of the tunneled ports so the protocol tunnels get established properly before the actual port itself is resumed. Othwerwise the USB/PCI core find the link may not be established and starts tearing down the device stack. This parses the ACPI description each time NHI is probed and tries to find devices that has the property and it references the NHI in question. For each matching device a device link from that device to the NHI is created. Since USB3 ports themselves do not get runtime suspended with the parent device (hub) we do not add the link from the USB3 port to USB4 NHI but instead we add the link from the xHCI device. This makes the device link usable for runtime PM as well. [1] https://www.usb.org/sites/default/files/D1T2-2%20-%20USB4%20on%20Windows.pdf Cc: Rafael J. Wysocki Signed-off-by: Mika Westerberg --- drivers/thunderbolt/Makefile | 2 + drivers/thunderbolt/acpi.c | 117 +++++++++++++++++++++++++++++++++++ drivers/thunderbolt/nhi.c | 1 + drivers/thunderbolt/tb.h | 6 ++ 4 files changed, 126 insertions(+) create mode 100644 drivers/thunderbolt/acpi.c diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 4ab5bfad7bfd..754a529aa132 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -4,4 +4,6 @@ thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o ee thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o thunderbolt-objs += nvm.o retimer.o quirks.o +thunderbolt-${CONFIG_ACPI} += acpi.o + obj-${CONFIG_USB4_KUNIT_TEST} += test.o diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c new file mode 100644 index 000000000000..a5f988a9f948 --- /dev/null +++ b/drivers/thunderbolt/acpi.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ACPI support + * + * Copyright (C) 2020, Intel Corporation + * Author: Mika Westerberg + */ + +#include + +#include "tb.h" + +static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, + void **return_value) +{ + struct fwnode_reference_args args; + struct fwnode_handle *fwnode; + struct tb_nhi *nhi = data; + struct acpi_device *adev; + struct pci_dev *pdev; + struct device *dev; + int ret; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + + fwnode = acpi_fwnode_handle(adev); + ret = fwnode_property_get_reference_args(fwnode, "usb4-host-interface", + NULL, 0, 0, &args); + if (ret) + return AE_OK; + + /* It needs to reference this NHI */ + if (nhi->pdev->dev.fwnode != args.fwnode) + goto out_put; + + /* + * Try to find physical device walking upwards to the hierarcy. + * We need to do this because the xHCI driver might not yet be + * bound so the USB3 SuperSpeed ports are not yet created. + */ + dev = acpi_get_first_physical_node(adev); + while (!dev) { + adev = adev->parent; + if (!adev) + break; + dev = acpi_get_first_physical_node(adev); + } + + if (!dev) + goto out_put; + + /* + * Check that the device is PCIe. This is because USB3 + * SuperSpeed ports have this property and they are not power + * managed with the xHCI and the SuperSpeed hub so we create the + * link from xHCI instead. + */ + while (!dev_is_pci(dev)) + dev = dev->parent; + + if (!dev) + goto out_put; + + /* + * Check that this actually matches the type of device we + * expect. It should either be xHCI or PCIe root/downstream + * port. + */ + pdev = to_pci_dev(dev); + if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI || + (pci_is_pcie(pdev) && + (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) { + const struct device_link *link; + + link = device_link_add(&pdev->dev, &nhi->pdev->dev, + DL_FLAG_AUTOREMOVE_SUPPLIER | + DL_FLAG_PM_RUNTIME); + if (link) { + dev_dbg(&nhi->pdev->dev, "created link from %s\n", + dev_name(&pdev->dev)); + } else { + dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", + dev_name(&pdev->dev)); + } + } + +out_put: + fwnode_handle_put(args.fwnode); + return AE_OK; +} + +/** + * tb_acpi_add_links() - Add device links based on ACPI description + * @nhi: Pointer to NHI + * + * Goes over ACPI namespace finding tunneled ports that reference to + * @nhi ACPI node. For each reference a device link is added. The link + * is automatically removed by the driver core. + */ +void tb_acpi_add_links(struct tb_nhi *nhi) +{ + acpi_status status; + + if (!has_acpi_companion(&nhi->pdev->dev)) + return; + + /* + * Find all devices that have usb4-host-controller interface + * property that references to this NHI. + */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32, + tb_acpi_add_link, NULL, nhi, NULL); + if (ACPI_FAILURE(status)) + dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n"); +} diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index e499fe78756b..bd24e8254336 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -1199,6 +1199,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) } tb_apple_add_links(nhi); + tb_acpi_add_links(nhi); tb = icm_probe(nhi); if (!tb) diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 847accd91bfa..dbcfa24caaf1 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -967,4 +967,10 @@ int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, void tb_check_quirks(struct tb_switch *sw); +#ifdef CONFIG_ACPI +void tb_acpi_add_links(struct tb_nhi *nhi); +#else +static inline void tb_acpi_add_links(struct tb_nhi *nhi) { } +#endif + #endif