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: 1347759 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmdt5zPdz9sPB for ; Wed, 19 Aug 2020 22:03:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728268AbgHSMDW (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347743 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmXs0cRVz9sPB for ; Wed, 19 Aug 2020 21:59:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728477AbgHSL7T (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347742 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmXn692tz9sPf for ; Wed, 19 Aug 2020 21:59:21 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728476AbgHSL7T (ORCPT ); Wed, 19 Aug 2020 07:59:19 -0400 Received: from mga03.intel.com ([134.134.136.65]:50012 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728357AbgHSL7N (ORCPT ); Wed, 19 Aug 2020 07:59:13 -0400 IronPort-SDR: DLQJhcqScln7J7x0Z09Qul6nInTS5H2qXfGnBmMEYrpJHEXAmi7wpc3Pruks6dHLC8EgBMo5nl E33YSXaHgW6g== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="155060155" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="155060155" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2020 04:59:10 -0700 IronPort-SDR: jlJ1sNCxmI3NEFOl3iykLMYBESZ9h6W1Un94eLawz7S9fIFbNuDcnWkTcDLVHNNVDlVlCDPQB8 n30go2nRjGMg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="279686688" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga008.fm.intel.com with ESMTP; 19 Aug 2020 04:59:07 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 69B84371; 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 03/19] thunderbolt: Software CM only should set force power in Tiger Lake Date: Wed, 19 Aug 2020 14:58:49 +0300 Message-Id: <20200819115905.59834-4-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org When Software CM is running it should not send any NHI mailbox command during PM flows. Only force power bit needs to be set and cleared so change Tiger Lake (well and Ice Lake) nhi_ops to take this into account. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/nhi_ops.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/thunderbolt/nhi_ops.c b/drivers/thunderbolt/nhi_ops.c index 28583f9faf46..96da07e88c52 100644 --- a/drivers/thunderbolt/nhi_ops.c +++ b/drivers/thunderbolt/nhi_ops.c @@ -121,31 +121,38 @@ static void icl_nhi_set_ltr(struct tb_nhi *nhi) static int icl_nhi_suspend(struct tb_nhi *nhi) { + struct tb *tb = pci_get_drvdata(nhi->pdev); int ret; if (icl_nhi_is_device_connected(nhi)) return 0; - /* - * If there is no device connected we need to perform both: a - * handshake through LC mailbox and force power down before - * entering D3. - */ - icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET); - ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); - if (ret) - return ret; + if (tb_switch_is_icm(tb->root_switch)) { + /* + * If there is no device connected we need to perform + * both: a handshake through LC mailbox and force power + * down before entering D3. + */ + icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET); + ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); + if (ret) + return ret; + } return icl_nhi_force_power(nhi, false); } static int icl_nhi_suspend_noirq(struct tb_nhi *nhi, bool wakeup) { + struct tb *tb = pci_get_drvdata(nhi->pdev); enum icl_lc_mailbox_cmd cmd; if (!pm_suspend_via_firmware()) return icl_nhi_suspend(nhi); + if (!tb_switch_is_icm(tb->root_switch)) + return 0; + cmd = wakeup ? ICL_LC_GO2SX : ICL_LC_GO2SX_NO_WAKE; icl_nhi_lc_mailbox_cmd(nhi, cmd); return icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); From patchwork Wed Aug 19 11:58:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347760 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmf62j7Gz9sPB for ; Wed, 19 Aug 2020 22:03:58 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728110AbgHSMD4 (ORCPT ); Wed, 19 Aug 2020 08:03:56 -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 S1728428AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: l8/2vkKrendYAOY5dt55fAjIQeqs/iwsYwBxdysla/ruPmxw9GrDpDrDYqQsFOrpSHcd2ri7xN ySuyWS8f2ZtQ== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="135160286" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="135160286" 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: lftiw1FH3jp+HE7eT6XXBSDQojVdz98HP+OoElTmQvNIk8KupFMrlo9xWfunLeWueYq633x+Kz g/Qr0DEnZvBg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="336938679" 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 74B48374; 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 04/19] thunderbolt: Use bit 31 to check if Firmware CM is running in Tiger Lake Date: Wed, 19 Aug 2020 14:58:50 +0300 Message-Id: <20200819115905.59834-5-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org In Tiger Lake the Firmware CM is always enabled (so bit 0 is always set) but it may be in "pass through" mode which means it requires Software CM instead. This can be determined by checking bit 31 instead. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/icm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index ffcc8c3459e5..b51fc3f62b1f 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -1635,11 +1635,14 @@ static void icm_icl_rtd3_veto(struct tb *tb, const struct icm_pkg_header *hdr) static bool icm_tgl_is_supported(struct tb *tb) { + u32 val; + /* * If the firmware is not running use software CM. This platform * should fully support both. */ - return icm_firmware_running(tb->nhi); + val = ioread32(tb->nhi->iobase + REG_FW_STS); + return !!(val & REG_FW_STS_NVM_AUTH_DONE); } static void icm_handle_notification(struct work_struct *work) 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: 1347746 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmZs2Xpvz9sPB for ; Wed, 19 Aug 2020 22:01:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727987AbgHSL7x (ORCPT ); Wed, 19 Aug 2020 07:59:53 -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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347758 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmds5Jq8z9sPB for ; Wed, 19 Aug 2020 22:03:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728341AbgHSMDh (ORCPT ); Wed, 19 Aug 2020 08:03:37 -0400 Received: from mga17.intel.com ([192.55.52.151]:31811 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728267AbgHSL7R (ORCPT ); Wed, 19 Aug 2020 07:59:17 -0400 IronPort-SDR: IQSHdSXZfcOWJ2HEDRWSH1vXque5nlT/GhdWsuqiIlEEp4jsHDehfiPlkfnkiUsjTEqvK6Sc8G dm9VJT7Qwyww== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="135160295" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="135160295" 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:14 -0700 IronPort-SDR: Q2tBAFzBTYLZwmtUGiYdu/Dkje2Ff7CojEAcA07M6JR/2YkGOcuyLsm06vn2t2C9ROrP0r8l49 7dOCSQaYLrqw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="336938686" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga007.jf.intel.com with ESMTP; 19 Aug 2020 04:59:11 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 8AA953D3; 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 06/19] thunderbolt: No need to log an error if tb_switch_lane_bonding_enable() fails Date: Wed, 19 Aug 2020 14:58:52 +0300 Message-Id: <20200819115905.59834-7-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org The function already logs an error if it fails so get rid of the duplication. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index f507815040eb..98f268a818a0 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -592,8 +592,7 @@ static void tb_scan_port(struct tb_port *port) } /* Enable lane bonding if supported */ - if (tb_switch_lane_bonding_enable(sw)) - tb_sw_warn(sw, "failed to enable lane bonding\n"); + tb_switch_lane_bonding_enable(sw); if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to enable TMU\n"); @@ -1245,8 +1244,7 @@ static void tb_restore_children(struct tb_switch *sw) if (!tb_port_has_remote(port)) continue; - if (tb_switch_lane_bonding_enable(port->remote->sw)) - dev_warn(&sw->dev, "failed to restore lane bonding\n"); + tb_switch_lane_bonding_enable(port->remote->sw); tb_restore_children(port->remote->sw); } 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: 1347745 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmYP1VGkz9sPB for ; Wed, 19 Aug 2020 21:59:53 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728494AbgHSL7b (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347751 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmcb1hwxz9sRK for ; Wed, 19 Aug 2020 22:02:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728499AbgHSL7a (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347757 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmdh5ylvz9sPB for ; Wed, 19 Aug 2020 22:03:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728117AbgHSMDV (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347754 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmcm2yddz9sPB for ; Wed, 19 Aug 2020 22:02:48 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728350AbgHSMCm (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: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: 1347744 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmXz6PgBz9sPB for ; Wed, 19 Aug 2020 21:59:31 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728497AbgHSL73 (ORCPT ); Wed, 19 Aug 2020 07:59:29 -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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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:58:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347755 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmcp1rGGz9sPf for ; Wed, 19 Aug 2020 22:02:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728356AbgHSMCo (ORCPT ); Wed, 19 Aug 2020 08:02:44 -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 S1728467AbgHSL7S (ORCPT ); Wed, 19 Aug 2020 07:59:18 -0400 IronPort-SDR: KbSCkfzyQ1/fg0ETZf9hyu64kPg4Y8yrSikqgjJLB2SA7fd0B4TkH/mDFFPfRRToCvToazvZ6v BjgrAFVuAbTg== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922670" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922670" 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: avVy1w0z+mAauYiDQZDZCgLFig7bmX2LHOQKkBXqLmOhv7WEfmlRbsaubXDb8ArWfAn8nyBMbY Du0Qzkdhf7tg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310758" 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 C543B5FF; 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 12/19] thunderbolt: Set port configured for both ends of the link Date: Wed, 19 Aug 2020 14:58:58 +0300 Message-Id: <20200819115905.59834-13-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Both ends of the link needs to have this set. Otherwise the link is not re-established properly after sleep. Now since it is possible to have mixed USB4 and Thunderbolt 1, 2 and 3 devices we need to split the link configuration functionality to happen per port so we can pick the correct implementation. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/lc.c | 48 +++++-------------- drivers/thunderbolt/switch.c | 33 ++++++++++--- drivers/thunderbolt/tb.h | 8 ++-- drivers/thunderbolt/usb4.c | 92 +++++++++++++++++------------------- 4 files changed, 87 insertions(+), 94 deletions(-) diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index b2f62ba0421d..5c209a570360 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -45,7 +45,7 @@ static int find_port_lc_cap(struct tb_port *port) return sw->cap_lc + start + phys * size; } -static int tb_lc_configure_lane(struct tb_port *port, bool configure) +static int tb_lc_set_port_configured(struct tb_port *port, bool configured) { bool upstream = tb_is_upstream_port(port); struct tb_switch *sw = port->sw; @@ -69,7 +69,7 @@ static int tb_lc_configure_lane(struct tb_port *port, bool configure) else lane = TB_LC_SX_CTRL_L2C; - if (configure) { + if (configured) { ctrl |= lane; if (upstream) ctrl |= TB_LC_SX_CTRL_UPSTREAM; @@ -83,49 +83,25 @@ static int tb_lc_configure_lane(struct tb_port *port, bool configure) } /** - * tb_lc_configure_link() - Let LC know about configured link - * @sw: Switch that is being added + * tb_lc_configure_port() - Let LC know about configured port + * @port: Port that is set as configured * - * Informs LC of both parent switch and @sw that there is established - * link between the two. + * Sets the port configured for power management purposes. */ -int tb_lc_configure_link(struct tb_switch *sw) +int tb_lc_configure_port(struct tb_port *port) { - struct tb_port *up, *down; - int ret; - - up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); - - /* Configure parent link toward this switch */ - ret = tb_lc_configure_lane(down, true); - if (ret) - return ret; - - /* Configure upstream link from this switch to the parent */ - ret = tb_lc_configure_lane(up, true); - if (ret) - tb_lc_configure_lane(down, false); - - return ret; + return tb_lc_set_port_configured(port, true); } /** - * tb_lc_unconfigure_link() - Let LC know about unconfigured link - * @sw: Switch to unconfigure + * tb_lc_unconfigure_port() - Let LC know about unconfigured port + * @port: Port that is set as configured * - * Informs LC of both parent switch and @sw that the link between the - * two does not exist anymore. + * Sets the port unconfigured for power management purposes. */ -void tb_lc_unconfigure_link(struct tb_switch *sw) +void tb_lc_unconfigure_port(struct tb_port *port) { - struct tb_port *up, *down; - - up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); - - tb_lc_configure_lane(up, false); - tb_lc_configure_lane(down, false); + tb_lc_set_port_configured(port, false); } /** diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index ecc47ea81bb6..1c45f8baf487 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2321,12 +2321,24 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) */ int tb_switch_configure_link(struct tb_switch *sw) { + struct tb_port *up, *down; + int ret; + 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); + up = tb_upstream_port(sw); + if (tb_switch_is_usb4(up->sw)) + ret = usb4_port_configure(up); + else + ret = tb_lc_configure_port(up); + if (ret) + return ret; + + down = up->remote; + if (tb_switch_is_usb4(down->sw)) + return usb4_port_configure(down); + return tb_lc_configure_port(down); } /** @@ -2338,15 +2350,24 @@ int tb_switch_configure_link(struct tb_switch *sw) */ void tb_switch_unconfigure_link(struct tb_switch *sw) { + struct tb_port *up, *down; + 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); + up = tb_upstream_port(sw); + if (tb_switch_is_usb4(up->sw)) + usb4_port_unconfigure(up); + else + tb_lc_unconfigure_port(up); + + down = up->remote; + if (tb_switch_is_usb4(down->sw)) + usb4_port_unconfigure(down); else - tb_lc_unconfigure_link(sw); + tb_lc_unconfigure_port(down); } /** diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index dcdc886412f5..082ae9da4cbc 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -846,8 +846,8 @@ int tb_drom_read(struct tb_switch *sw); 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_link(struct tb_switch *sw); -void tb_lc_unconfigure_link(struct tb_switch *sw); +int tb_lc_configure_port(struct tb_port *port); +void tb_lc_unconfigure_port(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); @@ -902,8 +902,6 @@ int usb4_switch_setup(struct tb_switch *sw); 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); -int usb4_switch_configure_link(struct tb_switch *sw); -void usb4_switch_unconfigure_link(struct tb_switch *sw); bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); int usb4_switch_set_sleep(struct tb_switch *sw); int usb4_switch_nvm_sector_size(struct tb_switch *sw); @@ -921,6 +919,8 @@ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, const struct tb_port *port); 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_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/usb4.c b/drivers/thunderbolt/usb4.c index dd601a6db23c..b2677427789f 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -338,54 +338,6 @@ int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, usb4_switch_drom_read_block, sw); } -static int usb4_set_port_configured(struct tb_port *port, bool configured) -{ - int ret; - u32 val; - - 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_PC; - else - val &= ~PORT_CS_19_PC; - - return tb_port_write(port, &val, TB_CFG_PORT, - port->cap_usb4 + PORT_CS_19, 1); -} - -/** - * usb4_switch_configure_link() - Set upstream USB4 link configured - * @sw: USB4 router - * - * Sets the upstream USB4 link to be configured for power management - * purposes. - */ -int usb4_switch_configure_link(struct tb_switch *sw) -{ - struct tb_port *up; - - up = tb_upstream_port(sw); - return usb4_set_port_configured(up, true); -} - -/** - * usb4_switch_unconfigure_link() - Un-set upstream USB4 link configuration - * @sw: USB4 router - * - * Reverse of usb4_switch_configure_link(). - */ -void usb4_switch_unconfigure_link(struct tb_switch *sw) -{ - struct tb_port *up; - - up = tb_upstream_port(sw); - usb4_set_port_configured(up, false); -} - /** * usb4_switch_lane_bonding_possible() - Are conditions met for lane bonding * @sw: USB4 router @@ -789,6 +741,50 @@ int usb4_port_unlock(struct tb_port *port) return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1); } +static int usb4_port_set_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_PC; + else + val &= ~PORT_CS_19_PC; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); +} + +/** + * usb4_port_configure() - Set USB4 port configured + * @port: USB4 router + * + * Sets the USB4 link to be configured for power management purposes. + */ +int usb4_port_configure(struct tb_port *port) +{ + return usb4_port_set_configured(port, true); +} + +/** + * usb4_port_unconfigure() - Set USB4 port unconfigured + * @port: USB4 router + * + * Sets the USB4 link to be unconfigured for power management purposes. + */ +void usb4_port_unconfigure(struct tb_port *port) +{ + usb4_port_set_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: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: 1347747 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmbF3TcDz9sPB for ; Wed, 19 Aug 2020 22:01:29 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728106AbgHSMAx (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347752 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmcg02G5z9sPB for ; Wed, 19 Aug 2020 22:02:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728068AbgHSMCk (ORCPT ); Wed, 19 Aug 2020 08:02:40 -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 S1728490AbgHSL7X (ORCPT ); Wed, 19 Aug 2020 07:59:23 -0400 IronPort-SDR: PuSeqyQr/q0KizfHJUuvlehAgLjvmVXGjmyaUtYjRFK58r+1A1liW+9kW8tJOCV3FY5HUIUNJe 8ycoN/zSEbwQ== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922671" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922671" 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: BeDZnOWaqfnl4JgJphoLH1l/+9bRLuDcmINtHUYnxJDJJOKiPC0Ujg/WnHwXv924P/2yue77Zw bUYjKahQtsjg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310760" 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 D76666BF; 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 14/19] thunderbolt: Disable lane 1 for XDomain connection Date: Wed, 19 Aug 2020 14:59:00 +0300 Message-Id: <20200819115905.59834-15-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org USB4 spec mandates that the lane 1 should be disabled if lanes are not bonded. For host-to-host connections (XDomain) we don't support lane bonding so in order to be compatible with the spec, disable lane 1 when another host is connected. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 44 +++++++++++++++++++++++++++++++++++ drivers/thunderbolt/tb.c | 8 +++++++ drivers/thunderbolt/tb.h | 2 ++ drivers/thunderbolt/tb_regs.h | 1 + 4 files changed, 55 insertions(+) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 1c45f8baf487..a8df25dae57b 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -673,6 +673,50 @@ int tb_port_unlock(struct tb_port *port) return 0; } +static int __tb_port_enable(struct tb_port *port, bool enable) +{ + int ret; + u32 phy; + + if (!tb_port_is_null(port)) + return -EINVAL; + + ret = tb_port_read(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); + if (ret) + return ret; + + if (enable) + phy &= ~LANE_ADP_CS_1_LD; + else + phy |= LANE_ADP_CS_1_LD; + + return tb_port_write(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); +} + +/** + * tb_port_enable() - Enable lane adapter + * @port: Port to enable (can be %NULL) + * + * This is used for lane 0 and 1 adapters to enable it. + */ +int tb_port_enable(struct tb_port *port) +{ + return __tb_port_enable(port, true); +} + +/** + * tb_port_disable() - Disable lane adapter + * @port: Port to disable (can be %NULL) + * + * This is used for lane 0 and 1 adapters to disable it. + */ +int tb_port_disable(struct tb_port *port) +{ + return __tb_port_enable(port, false); +} + /** * tb_init_port() - initialize a port * diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 602e00e0b45e..214e47656be6 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -142,6 +142,12 @@ static void tb_discover_tunnels(struct tb_switch *sw) static int tb_port_configure_xdomain(struct tb_port *port) { + /* + * XDomain paths currently only support single lane so we must + * disable the other lane according to USB4 spec. + */ + tb_port_disable(port->dual_link_port); + if (tb_switch_is_usb4(port->sw)) return usb4_port_configure_xdomain(port); return tb_lc_configure_xdomain(port); @@ -153,6 +159,8 @@ static void tb_port_unconfigure_xdomain(struct tb_port *port) usb4_port_unconfigure_xdomain(port); else tb_lc_unconfigure_xdomain(port); + + tb_port_enable(port->dual_link_port); } static void tb_scan_xdomain(struct tb_port *port) diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index dbe332c3e95e..f58cd3fa98ea 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -790,6 +790,8 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits); int tb_port_set_initial_credits(struct tb_port *port, u32 credits); int tb_port_clear_counter(struct tb_port *port, int counter); int tb_port_unlock(struct tb_port *port); +int tb_port_enable(struct tb_port *port); +int tb_port_disable(struct tb_port *port); int tb_port_alloc_in_hopid(struct tb_port *port, int hopid, int max_hopid); void tb_port_release_in_hopid(struct tb_port *port, int hopid); int tb_port_alloc_out_hopid(struct tb_port *port, int hopid, int max_hopid); diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index a553be24f1c0..d1a40baa63d2 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -279,6 +279,7 @@ struct tb_regs_port_header { #define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4 #define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1 #define LANE_ADP_CS_1_TARGET_WIDTH_DUAL 0x3 +#define LANE_ADP_CS_1_LD BIT(14) #define LANE_ADP_CS_1_LB BIT(15) #define LANE_ADP_CS_1_CURRENT_SPEED_MASK GENMASK(19, 16) #define LANE_ADP_CS_1_CURRENT_SPEED_SHIFT 16 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: 1347756 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmd04xNYz9sPf for ; Wed, 19 Aug 2020 22:03:00 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728380AbgHSMCq (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347748 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmbV1RQMz9sPf for ; Wed, 19 Aug 2020 22:01:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727986AbgHSMB3 (ORCPT ); Wed, 19 Aug 2020 08:01:29 -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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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 Acked-by: Bjorn Helgaas --- 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); 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: 1347749 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmbV4QQlz9sRK for ; Wed, 19 Aug 2020 22:01:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728137AbgHSMBa (ORCPT ); Wed, 19 Aug 2020 08:01: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 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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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: 1347753 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmch1qMGz9sPB for ; Wed, 19 Aug 2020 22:02:44 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728344AbgHSMCm (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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@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 From patchwork Wed Aug 19 11:59:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 1347750 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BWmcZ4pmTz9sPf for ; Wed, 19 Aug 2020 22:02:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728183AbgHSMCA (ORCPT ); Wed, 19 Aug 2020 08:02:00 -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 S1728320AbgHSMAa (ORCPT ); Wed, 19 Aug 2020 08:00:30 -0400 IronPort-SDR: mE2Gm7E84XMjmpaqyfWYSPi1cbSQJPA1ML+Wc4uY4LRDJHdFSlCynpWm71NcBiNRDWyyPBe8/X KgsFMhl68iKQ== X-IronPort-AV: E=McAfee;i="6000,8403,9717"; a="239922679" X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="239922679" 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: lshPPTxGcuG/kQKHKMECxhlFh8ZAVwSYXqu6z99uVxRlcrVSwBAqXEwmbI+drxC0FL/cU8UkPb ls9M3s1iFjiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,331,1592895600"; d="scan'208";a="329310790" 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 1228F8B7; 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 19/19] thunderbolt: Add runtime PM for Software CM Date: Wed, 19 Aug 2020 14:59:05 +0300 Message-Id: <20200819115905.59834-20-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-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This adds runtime PM support for the Software Connection Manager parts of the driver. This allows to save power when either there is no device attached at all or there is a device attached and all following conditions are true: - Tunneled PCIe root/downstream ports are runtime suspended - Tunneled USB3 ports are runtime suspended - No active DisplayPort stream - No active XDomain connection For the first two we take advantage of device links that were added in previous patch. Difference for the system sleep case is that we also enable wakes when something is geting plugged in/out of the Thunderbolt ports. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 25 ++++++-- drivers/thunderbolt/tb.c | 116 ++++++++++++++++++++++++++++++++++- drivers/thunderbolt/tb.h | 2 +- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index a2ebf51ac389..db63b5eb9467 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2679,23 +2679,40 @@ int tb_switch_resume(struct tb_switch *sw) return 0; } -void tb_switch_suspend(struct tb_switch *sw) +/** + * tb_switch_suspend() - Put a switch to sleep + * @sw: Switch to suspend + * @runtime: Is this runtime suspend or system sleep + * + * Suspends router and all its children. Enables wakes according to + * value of @runtime and then sets sleep bit for the router. If @sw is + * host router the domain is ready to go to sleep once this function + * returns. + */ +void tb_switch_suspend(struct tb_switch *sw, bool runtime) { unsigned int flags = 0; struct tb_port *port; int err; + tb_sw_dbg(sw, "suspending switch\n"); + err = tb_plug_events_active(sw, false); if (err) return; tb_switch_for_each_port(sw, port) { if (tb_port_has_remote(port)) - tb_switch_suspend(port->remote->sw); + tb_switch_suspend(port->remote->sw, runtime); } - if (device_may_wakeup(&sw->dev)) - flags = TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; + if (runtime) { + /* Trigger wake when something is plugged in/out */ + flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT; + flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; + } else 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); diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 214e47656be6..170d1d846557 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "tb.h" #include "tb_regs.h" @@ -22,13 +23,21 @@ * events and exit if this is not set (it needs to * acquire the lock one more time). Used to drain wq * after cfg has been paused. + * @remove_work: Work used to remove any unplugged routers after + * runtime resume */ struct tb_cm { struct list_head tunnel_list; struct list_head dp_resources; bool hotplug_active; + struct delayed_work remove_work; }; +static inline struct tb *tcm_to_tb(struct tb_cm *tcm) +{ + return ((void *)tcm - sizeof(struct tb)); +} + struct tb_hotplug_event { struct work_struct work; struct tb *tb; @@ -526,8 +535,13 @@ static void tb_scan_switch(struct tb_switch *sw) { struct tb_port *port; + pm_runtime_get_sync(&sw->dev); + tb_switch_for_each_port(sw, port) tb_scan_port(port); + + pm_runtime_mark_last_busy(&sw->dev); + pm_runtime_put_autosuspend(&sw->dev); } /** @@ -602,6 +616,12 @@ static void tb_scan_port(struct tb_port *port) if (!tcm->hotplug_active) dev_set_uevent_suppress(&sw->dev, true); + /* + * At the moment Thunderbolt 2 and beyond (devices with LC) we + * can support runtime PM. + */ + sw->rpm = sw->generation > 1; + if (tb_switch_add(sw)) { tb_switch_put(sw); return; @@ -662,6 +682,11 @@ static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel) * deallocated properly. */ tb_switch_dealloc_dp_resource(src_port->sw, src_port); + /* Now we can allow the domain to runtime suspend again */ + pm_runtime_mark_last_busy(&dst_port->sw->dev); + pm_runtime_put_autosuspend(&dst_port->sw->dev); + pm_runtime_mark_last_busy(&src_port->sw->dev); + pm_runtime_put_autosuspend(&src_port->sw->dev); fallthrough; case TB_TUNNEL_USB3: @@ -848,9 +873,20 @@ static void tb_tunnel_dp(struct tb *tb) return; } + /* + * DP stream needs the domain to be active so runtime resume + * both ends of the tunnel. + * + * This should bring the routers in the middle active as well + * and keeps the domain from runtime suspending while the DP + * tunnel is active. + */ + pm_runtime_get_sync(&in->sw->dev); + pm_runtime_get_sync(&out->sw->dev); + if (tb_switch_alloc_dp_resource(in->sw, in)) { tb_port_dbg(in, "no resource available for DP IN, not tunneling\n"); - return; + goto err_rpm_put; } /* Make all unused USB3 bandwidth available for the new DP tunnel */ @@ -889,6 +925,11 @@ static void tb_tunnel_dp(struct tb *tb) tb_reclaim_usb3_bandwidth(tb, in, out); err_dealloc_dp: tb_switch_dealloc_dp_resource(in->sw, in); +err_rpm_put: + pm_runtime_mark_last_busy(&out->sw->dev); + pm_runtime_put_autosuspend(&out->sw->dev); + pm_runtime_mark_last_busy(&in->sw->dev); + pm_runtime_put_autosuspend(&in->sw->dev); } static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port) @@ -1073,6 +1114,9 @@ static void tb_handle_hotplug(struct work_struct *work) struct tb_switch *sw; struct tb_port *port; + /* Bring the domain back from sleep if it was suspended */ + pm_runtime_get_sync(&tb->dev); + mutex_lock(&tb->lock); if (!tcm->hotplug_active) goto out; /* during init, suspend or shutdown */ @@ -1096,6 +1140,9 @@ static void tb_handle_hotplug(struct work_struct *work) ev->route, ev->port, ev->unplug); goto put_sw; } + + pm_runtime_get_sync(&sw->dev); + if (ev->unplug) { tb_retimer_remove_all(port); @@ -1149,10 +1196,17 @@ static void tb_handle_hotplug(struct work_struct *work) } } + pm_runtime_mark_last_busy(&sw->dev); + pm_runtime_put_autosuspend(&sw->dev); + put_sw: tb_switch_put(sw); out: mutex_unlock(&tb->lock); + + pm_runtime_mark_last_busy(&tb->dev); + pm_runtime_put_autosuspend(&tb->dev); + kfree(ev); } @@ -1188,6 +1242,7 @@ static void tb_stop(struct tb *tb) struct tb_tunnel *tunnel; struct tb_tunnel *n; + cancel_delayed_work(&tcm->remove_work); /* tunnels are only present after everything has been initialized */ list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) { /* @@ -1239,6 +1294,8 @@ static int tb_start(struct tb *tb) * root switch. */ tb->root_switch->no_nvm_upgrade = true; + /* All USB4 routers support runtime PM */ + tb->root_switch->rpm = tb_switch_is_usb4(tb->root_switch); ret = tb_switch_configure(tb->root_switch); if (ret) { @@ -1281,7 +1338,7 @@ static int tb_suspend_noirq(struct tb *tb) tb_dbg(tb, "suspending...\n"); tb_disconnect_and_release_dp(tb); - tb_switch_suspend(tb->root_switch); + tb_switch_suspend(tb->root_switch, false); tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */ tb_dbg(tb, "suspend finished\n"); @@ -1292,6 +1349,10 @@ static void tb_restore_children(struct tb_switch *sw) { struct tb_port *port; + /* No need to restore if the router is already unplugged */ + if (sw->is_unplugged) + return; + if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to restore TMU configuration\n"); @@ -1376,12 +1437,62 @@ static void tb_complete(struct tb *tb) mutex_unlock(&tb->lock); } +static int tb_runtime_suspend(struct tb *tb) +{ + struct tb_cm *tcm = tb_priv(tb); + + mutex_lock(&tb->lock); + tb_switch_suspend(tb->root_switch, true); + tcm->hotplug_active = false; + mutex_unlock(&tb->lock); + + return 0; +} + +static void tb_remove_work(struct work_struct *work) +{ + struct tb_cm *tcm = container_of(work, struct tb_cm, remove_work.work); + struct tb *tb = tcm_to_tb(tcm); + + mutex_lock(&tb->lock); + if (tb->root_switch) { + tb_free_unplugged_children(tb->root_switch); + tb_free_unplugged_xdomains(tb->root_switch); + } + mutex_unlock(&tb->lock); +} + +static int tb_runtime_resume(struct tb *tb) +{ + struct tb_cm *tcm = tb_priv(tb); + struct tb_tunnel *tunnel, *n; + + mutex_lock(&tb->lock); + tb_switch_resume(tb->root_switch); + tb_free_invalid_tunnels(tb); + tb_restore_children(tb->root_switch); + list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) + tb_tunnel_restart(tunnel); + tcm->hotplug_active = true; + mutex_unlock(&tb->lock); + + /* + * Schedule cleanup of any unplugged devices. Run this in a + * separate thread to avoid possible deadlock if the device + * removal runtime resumes the unplugged device. + */ + queue_delayed_work(tb->wq, &tcm->remove_work, msecs_to_jiffies(50)); + return 0; +} + static const struct tb_cm_ops tb_cm_ops = { .start = tb_start, .stop = tb_stop, .suspend_noirq = tb_suspend_noirq, .resume_noirq = tb_resume_noirq, .complete = tb_complete, + .runtime_suspend = tb_runtime_suspend, + .runtime_resume = tb_runtime_resume, .handle_event = tb_handle_event, .approve_switch = tb_tunnel_pci, .approve_xdomain_paths = tb_approve_xdomain_paths, @@ -1403,6 +1514,7 @@ struct tb *tb_probe(struct tb_nhi *nhi) tcm = tb_priv(tb); INIT_LIST_HEAD(&tcm->tunnel_list); INIT_LIST_HEAD(&tcm->dp_resources); + INIT_DELAYED_WORK(&tcm->remove_work, tb_remove_work); return tb; } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index dbcfa24caaf1..7c8f505e6818 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -639,7 +639,7 @@ struct tb_switch *tb_switch_alloc_safe_mode(struct tb *tb, int tb_switch_configure(struct tb_switch *sw); int tb_switch_add(struct tb_switch *sw); void tb_switch_remove(struct tb_switch *sw); -void tb_switch_suspend(struct tb_switch *sw); +void tb_switch_suspend(struct tb_switch *sw, bool runtime); int tb_switch_resume(struct tb_switch *sw); int tb_switch_reset(struct tb_switch *sw); void tb_sw_set_unplugged(struct tb_switch *sw);