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: 251731 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 3E913C433DF 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 0433C206DA for ; Wed, 19 Aug 2020 12:03:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728295AbgHSMDW (ORCPT ); Wed, 19 Aug 2020 08:03:22 -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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@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: 251738 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 891ABC433DF 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 6441A2072D for ; Wed, 19 Aug 2020 11:59:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728478AbgHSL7T (ORCPT ); Wed, 19 Aug 2020 07:59:19 -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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@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:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 251737 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 5F6C4C433E3 for ; Wed, 19 Aug 2020 12:00:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4B2132075E for ; Wed, 19 Aug 2020 12:00:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728503AbgHSL7b (ORCPT ); Wed, 19 Aug 2020 07:59:31 -0400 Received: from mga11.intel.com ([192.55.52.93]:23197 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728453AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: jkgx8MdRyBTdVo8Y2ycmSS9Y4UbPJ34a1ao272IYd1BELj3dJStEv+h8sDpYd62VbK5L0BTqQe LkEU9aRZ785w== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="152708174" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="152708174" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:14 -0700 IronPort-SDR: Nttxb4+YcF2yr3xWeLrmOtQkjZYMskIXL2yWeXYUHPXmATj3QmhtGB82UaaTpBcau3TsW3Cn1a z8kRFV3xNz4Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="400804657" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 960A43DF; 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 07/19] thunderbolt: Send reset only to first generation routers Date: Wed, 19 Aug 2020 14:58:53 +0300 Message-Id: <20200819115905.59834-8-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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org First generation routers may need the reset command upon resume but it is not supported by newer generations. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 21 +++++++++++---------- drivers/thunderbolt/tb.c | 2 +- drivers/thunderbolt/tb.h | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 72756c8ceead..fb30ea1dfc31 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1234,23 +1234,24 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw) /** * reset_switch() - reconfigure route, enable and send TB_CFG_PKG_RESET + * @sw: Switch to reset * * Return: Returns 0 on success or an error code on failure. */ -int tb_switch_reset(struct tb *tb, u64 route) +int tb_switch_reset(struct tb_switch *sw) { struct tb_cfg_result res; - struct tb_regs_switch_header header = { - header.route_hi = route >> 32, - header.route_lo = route, - header.enabled = true, - }; - tb_dbg(tb, "resetting switch at %llx\n", route); - res.err = tb_cfg_write(tb->ctl, ((u32 *) &header) + 2, route, - 0, 2, 2, 2); + + if (sw->generation > 1) + return 0; + + tb_sw_dbg(sw, "resetting switch\n"); + + res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2, + TB_CFG_SWITCH, 2, 2); if (res.err) return res.err; - res = tb_cfg_reset(tb->ctl, route, TB_CFG_DEFAULT_TIMEOUT); + res = tb_cfg_reset(sw->tb->ctl, tb_route(sw), TB_CFG_DEFAULT_TIMEOUT); if (res.err > 0) return -EIO; return res.err; diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 98f268a818a0..a6da2d0567ae 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1258,7 +1258,7 @@ static int tb_resume_noirq(struct tb *tb) tb_dbg(tb, "resuming...\n"); /* remove any pci devices the firmware might have setup */ - tb_switch_reset(tb, 0); + tb_switch_reset(tb->root_switch); tb_switch_resume(tb->root_switch); tb_free_invalid_tunnels(tb); diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index df08f6d7aaa0..69e78bbed53a 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -634,7 +634,7 @@ int tb_switch_add(struct tb_switch *sw); void tb_switch_remove(struct tb_switch *sw); void tb_switch_suspend(struct tb_switch *sw); int tb_switch_resume(struct tb_switch *sw); -int tb_switch_reset(struct tb *tb, u64 route); +int tb_switch_reset(struct tb_switch *sw); void tb_sw_set_unplugged(struct tb_switch *sw); struct tb_port *tb_switch_find_port(struct tb_switch *sw, enum tb_port_type type); 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: 251734 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 7689CC433E1 for ; Wed, 19 Aug 2020 12:02:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4C09A206DA for ; Wed, 19 Aug 2020 12:02:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728502AbgHSL7a (ORCPT ); Wed, 19 Aug 2020 07:59:30 -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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@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: 251730 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 3FA3DC433E1 for ; Wed, 19 Aug 2020 12:03:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 06611205CB for ; Wed, 19 Aug 2020 12:03:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728273AbgHSMDV (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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@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:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 251733 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 43CA2C433E3 for ; Wed, 19 Aug 2020 12:02:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1F54D2078D for ; Wed, 19 Aug 2020 12:02:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728169AbgHSMCm (ORCPT ); Wed, 19 Aug 2020 08:02:42 -0400 Received: from mga05.intel.com ([192.55.52.43]:49568 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728493AbgHSL7W (ORCPT ); Wed, 19 Aug 2020 07:59:22 -0400 IronPort-SDR: SPbFxX9AevWWWeTISxfFlxTReWpzO40IHQhbJIzQDDi+NW2/TUqtCo8O5dnh+aUeB8Dvsai+HL WXH4p3UPoBVA== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922672" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922672" 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: knPXZSxeBqB46vVg835SwDONqzistVX9LP+zgOjtUm6K3bTUQD/cl/vtWwJ2EiM92V8d9ELxy/ czDMRiZ6stcA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310762" 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 B38634B3; 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 10/19] thunderbolt: Do not change default USB4 router notification timeout Date: Wed, 19 Aug 2020 14:58:56 +0300 Message-Id: <20200819115905.59834-11-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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Some early stage USB4 devices do not like that any of the enumerating router config space fields (ROUTER_CS_1 - ROUTER_CS_4) are written after the initial enumeration for example when entering sleep states. The default timeout by the USB4 spec is 10 ms which should be fine for the driver to handle. For this reason do not change the notification timeout from the default 10 ms for USB4 routers. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index de186d6ed166..e1ba8215144b 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1269,7 +1269,7 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) u32 data; int res; - if (tb_switch_is_icm(sw)) + if (tb_switch_is_icm(sw) || tb_switch_is_usb4(sw)) return 0; sw->config.plug_events_delay = 0xff; @@ -1277,10 +1277,6 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) if (res) return res; - /* Plug events are always enabled in USB4 */ - if (tb_switch_is_usb4(sw)) - return 0; - res = tb_sw_read(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1); if (res) return res; From patchwork Wed Aug 19 11:58:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 251736 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 42826C433E1 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 213CA205CB for ; Wed, 19 Aug 2020 12:01:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728063AbgHSMAx (ORCPT ); Wed, 19 Aug 2020 08:00:53 -0400 Received: from mga05.intel.com ([192.55.52.43]:49555 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727807AbgHSL7x (ORCPT ); Wed, 19 Aug 2020 07:59:53 -0400 IronPort-SDR: W+DdLoC+9vlXB9bb2N0is9Ry0Ehtg8ON8X4sIhF3JJTqwZlExEjewqMzH9BsHN8J5WBdWcZ3wN HneTjVCwFSCg== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922673" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922673" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:14 -0700 IronPort-SDR: WUm0ykx4GA/OhJSVT4Cx2Yc7W5T3nzYLqgOMINs2bwhSiqON0DmKvb7elpSsAkEucGGWcVn6kx 0g6hMMGp2kbA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="278309127" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga007.fm.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id CE3AF656; 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 13/19] thunderbolt: Configure port for XDomain Date: Wed, 19 Aug 2020 14:58:59 +0300 Message-Id: <20200819115905.59834-14-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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org When the port is connected to another host it should be marked as such in the USB4 port capability. This information is used by the router during sleep and wakeup. Also do the same for legacy switches via link controller vendor specific registers. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/lc.c | 54 +++++++++++++++++++++++++++++++++++ drivers/thunderbolt/tb.c | 32 ++++++++++++++++++--- drivers/thunderbolt/tb.h | 4 +++ drivers/thunderbolt/tb_regs.h | 3 ++ drivers/thunderbolt/usb4.c | 45 +++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 4 deletions(-) diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index 5c209a570360..44647fa1ec1c 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -104,6 +104,60 @@ void tb_lc_unconfigure_port(struct tb_port *port) tb_lc_set_port_configured(port, false); } +static int tb_lc_set_xdomain_configured(struct tb_port *port, bool configure) +{ + struct tb_switch *sw = port->sw; + u32 ctrl, lane; + int cap, ret; + + if (sw->generation < 2) + return 0; + + cap = find_port_lc_cap(port); + if (cap < 0) + return cap; + + ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1); + if (ret) + return ret; + + /* Resolve correct lane */ + if (port->port % 2) + lane = TB_LC_SX_CTRL_L1D; + else + lane = TB_LC_SX_CTRL_L2D; + + if (configure) + ctrl |= lane; + else + ctrl &= ~lane; + + return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1); +} + +/** + * tb_lc_configure_xdomain() - Inform LC that the link is XDomain + * @port: Switch downstream port connected to another host + * + * Sets the lane configured for XDomain accordingly so that the LC knows + * about this. Returns %0 in success and negative errno in failure. + */ +int tb_lc_configure_xdomain(struct tb_port *port) +{ + return tb_lc_set_xdomain_configured(port, true); +} + +/** + * tb_lc_unconfigure_xdomain() - Unconfigure XDomain from port + * @port: Switch downstream port that was connected to another host + * + * Unsets the lane XDomain configuration. + */ +void tb_lc_unconfigure_xdomain(struct tb_port *port) +{ + tb_lc_set_xdomain_configured(port, false); +} + /** * tb_lc_set_sleep() - Inform LC that the switch is going to sleep * @sw: Switch to set sleep diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 54a4daf0b1b4..602e00e0b45e 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -140,6 +140,21 @@ static void tb_discover_tunnels(struct tb_switch *sw) } } +static int tb_port_configure_xdomain(struct tb_port *port) +{ + if (tb_switch_is_usb4(port->sw)) + return usb4_port_configure_xdomain(port); + return tb_lc_configure_xdomain(port); +} + +static void tb_port_unconfigure_xdomain(struct tb_port *port) +{ + if (tb_switch_is_usb4(port->sw)) + usb4_port_unconfigure_xdomain(port); + else + tb_lc_unconfigure_xdomain(port); +} + static void tb_scan_xdomain(struct tb_port *port) { struct tb_switch *sw = port->sw; @@ -158,6 +173,7 @@ static void tb_scan_xdomain(struct tb_port *port) NULL); if (xd) { tb_port_at(route, sw)->xdomain = xd; + tb_port_configure_xdomain(port); tb_xdomain_add(xd); } } @@ -566,6 +582,7 @@ static void tb_scan_port(struct tb_port *port) */ if (port->xdomain) { tb_xdomain_remove(port->xdomain); + tb_port_unconfigure_xdomain(port); port->xdomain = NULL; } @@ -1047,6 +1064,7 @@ static void tb_handle_hotplug(struct work_struct *work) struct tb_cm *tcm = tb_priv(tb); struct tb_switch *sw; struct tb_port *port; + mutex_lock(&tb->lock); if (!tcm->hotplug_active) goto out; /* during init, suspend or shutdown */ @@ -1103,6 +1121,7 @@ static void tb_handle_hotplug(struct work_struct *work) port->xdomain = NULL; __tb_disconnect_xdomain_paths(tb, xd); tb_xdomain_put(xd); + tb_port_unconfigure_xdomain(port); } else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) { tb_dp_resource_unavailable(tb, port); } else { @@ -1269,13 +1288,17 @@ static void tb_restore_children(struct tb_switch *sw) tb_sw_warn(sw, "failed to restore TMU configuration\n"); tb_switch_for_each_port(sw, port) { - if (!tb_port_has_remote(port)) + if (!tb_port_has_remote(port) && !port->xdomain) continue; - tb_switch_lane_bonding_enable(port->remote->sw); - tb_switch_configure_link(port->remote->sw); + if (port->remote) { + tb_switch_lane_bonding_enable(port->remote->sw); + tb_switch_configure_link(port->remote->sw); - tb_restore_children(port->remote->sw); + tb_restore_children(port->remote->sw); + } else if (port->xdomain) { + tb_port_configure_xdomain(port); + } } } @@ -1321,6 +1344,7 @@ static int tb_free_unplugged_xdomains(struct tb_switch *sw) if (port->xdomain && port->xdomain->is_unplugged) { tb_retimer_remove_all(port); tb_xdomain_remove(port->xdomain); + tb_port_unconfigure_xdomain(port); port->xdomain = NULL; ret++; } else if (port->remote) { diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 082ae9da4cbc..dbe332c3e95e 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -848,6 +848,8 @@ int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid); 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_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); @@ -921,6 +923,8 @@ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, int usb4_port_unlock(struct tb_port *port); int usb4_port_configure(struct tb_port *port); void usb4_port_unconfigure(struct tb_port *port); +int usb4_port_configure_xdomain(struct tb_port *port); +void usb4_port_unconfigure_xdomain(struct tb_port *port); int usb4_port_enumerate_retimers(struct tb_port *port); int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index fd4fc144d17f..a553be24f1c0 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -303,6 +303,7 @@ struct tb_regs_port_header { #define PORT_CS_18_TCM BIT(9) #define PORT_CS_19 0x13 #define PORT_CS_19_PC BIT(3) +#define PORT_CS_19_PID BIT(4) /* Display Port adapter registers */ #define ADP_DP_CS_0 0x00 @@ -417,7 +418,9 @@ struct tb_regs_hop { #define TB_LC_SX_CTRL 0x96 #define TB_LC_SX_CTRL_L1C BIT(16) +#define TB_LC_SX_CTRL_L1D BIT(17) #define TB_LC_SX_CTRL_L2C BIT(20) +#define TB_LC_SX_CTRL_L2D BIT(21) #define TB_LC_SX_CTRL_UPSTREAM BIT(30) #define TB_LC_SX_CTRL_SLP BIT(31) diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index b2677427789f..59b8b51d1fa4 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -785,6 +785,51 @@ void usb4_port_unconfigure(struct tb_port *port) usb4_port_set_configured(port, false); } +static int usb4_set_xdomain_configured(struct tb_port *port, bool configured) +{ + int ret; + u32 val; + + if (!port->cap_usb4) + return -EINVAL; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + if (configured) + val |= PORT_CS_19_PID; + else + val &= ~PORT_CS_19_PID; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); +} + +/** + * usb4_port_configure_xdomain() - Configure port for XDomain + * @port: USB4 port connected to another host + * + * Marks the USB4 port as being connected to another host. Returns %0 in + * success and negative errno in failure. + */ +int usb4_port_configure_xdomain(struct tb_port *port) +{ + return usb4_set_xdomain_configured(port, true); +} + +/** + * usb4_port_unconfigure_xdomain() - Unconfigure port for XDomain + * @port: USB4 port that was connected to another host + * + * Clears USB4 port from being marked as XDomain. + */ +void usb4_port_unconfigure_xdomain(struct tb_port *port) +{ + usb4_set_xdomain_configured(port, false); +} + static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, u32 value, int timeout_msec) { 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: 251732 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 D5A68C433DF for ; Wed, 19 Aug 2020 12:03:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B3CD9206DA for ; Wed, 19 Aug 2020 12:03:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728377AbgHSMCq (ORCPT ); Wed, 19 Aug 2020 08:02:46 -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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@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:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 251735 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 70437C433E3 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 503F420888 for ; Wed, 19 Aug 2020 12:01:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728138AbgHSMBJ (ORCPT ); Wed, 19 Aug 2020 08:01:09 -0400 Received: from mga05.intel.com ([192.55.52.43]:49568 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727102AbgHSL7x (ORCPT ); Wed, 19 Aug 2020 07:59:53 -0400 IronPort-SDR: UUz4j6ybe5JRGO0NbWNzCbgpvxEenyVMPWEH1q4zFtRZm7g6OnwXPUct+/IMCwmp4FgOEOIv3b xH3KfRtnz4Vg== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922677" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922677" 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: aDIf1b0oZyDRsTxu1NRQT3+ecP3BgVbcoqkhLqALQQaAY/1TKR5udU/hBumleY+scJ4zs52UXp Jm+uO7zJDtLw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310785" 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 E81B436D; 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 16/19] PCI / thunderbolt: Switch to use device links instead of PCI quirk Date: Wed, 19 Aug 2020 14:59:02 +0300 Message-Id: <20200819115905.59834-17-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-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org On older Apple systems there is currently a PCI quirk in place to block resume of tunneled PCIe ports until NHI (Thunderbolt controller) is resumed. This makes sure the PCIe tunnels are re-established before PCI core notices it. With device links the same thing can be done without quirks. The driver core will make sure the supplier (NHI) is resumed before consumers (PCIe downstream ports). For this reason switch the Thunderbolt driver to use device links and remove the PCI quirk. Cc: Bjorn Helgaas Signed-off-by: Mika Westerberg --- drivers/pci/quirks.c | 57 --------------------------------- drivers/thunderbolt/nhi.c | 66 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bdf9b52567e0..a25471436523 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3673,63 +3673,6 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, quirk_apple_poweroff_thunderbolt); - -/* - * Apple: Wait for the Thunderbolt controller to reestablish PCI tunnels - * - * During suspend the Thunderbolt controller is reset and all PCI - * tunnels are lost. The NHI driver will try to reestablish all tunnels - * during resume. We have to manually wait for the NHI since there is - * no parent child relationship between the NHI and the tunneled - * bridges. - */ -static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) -{ - struct pci_dev *sibling = NULL; - struct pci_dev *nhi = NULL; - - if (!x86_apple_machine) - return; - if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) - return; - - /* - * Find the NHI and confirm that we are a bridge on the Thunderbolt - * host controller and not on a Thunderbolt endpoint. - */ - sibling = pci_get_slot(dev->bus, 0x0); - if (sibling == dev) - goto out; /* we are the downstream bridge to the NHI */ - if (!sibling || !sibling->subordinate) - goto out; - nhi = pci_get_slot(sibling->subordinate, 0x0); - if (!nhi) - goto out; - if (nhi->vendor != PCI_VENDOR_ID_INTEL - || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE && - nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && - nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI && - nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) - || nhi->class != PCI_CLASS_SYSTEM_OTHER << 8) - goto out; - pci_info(dev, "quirk: waiting for Thunderbolt to reestablish PCI tunnels...\n"); - device_pm_wait_for_dev(&dev->dev, &nhi->dev); -out: - pci_dev_put(nhi); - pci_dev_put(sibling); -} -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, - quirk_apple_wait_for_thunderbolt); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, - quirk_apple_wait_for_thunderbolt); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE, - quirk_apple_wait_for_thunderbolt); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE, - quirk_apple_wait_for_thunderbolt); #endif /* diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 24d2b7eff59b..e499fe78756b 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "nhi.h" #include "nhi_regs.h" @@ -1069,6 +1070,69 @@ static bool nhi_imr_valid(struct pci_dev *pdev) return true; } +/* + * During suspend the Thunderbolt controller is reset and all PCIe + * tunnels are lost. The NHI driver will try to reestablish all tunnels + * during resume. This adds device links between the tunneled PCIe + * downstream ports and the NHI so that the device core will make sure + * NHI is resumed first before the rest. + */ +static void tb_apple_add_links(struct tb_nhi *nhi) +{ + struct pci_dev *upstream, *pdev; + + if (!x86_apple_machine) + return; + + switch (nhi->pdev->device) { + case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: + case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: + case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: + case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: + break; + default: + return; + } + + upstream = pci_upstream_bridge(nhi->pdev); + while (upstream) { + if (!pci_is_pcie(upstream)) + return; + if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM) + break; + upstream = pci_upstream_bridge(upstream); + } + + if (!upstream) + return; + + /* + * For each hotplug downstream port, create add device link + * back to NHI so that PCIe tunnels can be re-established after + * sleep. + */ + for_each_pci_bridge(pdev, upstream->subordinate) { + const struct device_link *link; + + if (!pci_is_pcie(pdev)) + continue; + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM || + !pdev->is_hotplug_bridge) + continue; + + 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)); + } + } +} + static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tb_nhi *nhi; @@ -1134,6 +1198,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) return res; } + tb_apple_add_links(nhi); + tb = icm_probe(nhi); if (!tb) tb = tb_probe(nhi);