Received: by 2002:a05:6358:bb9e:b0:b9:5105:a5b4 with SMTP id df30csp2735620rwb; Mon, 5 Sep 2022 00:01:06 -0700 (PDT) X-Google-Smtp-Source: AA6agR6Y94w/ljCc5kwdfUoVHTPGPV3SaMqAHPDMpgQR577zWT91GGFGlo0e26nCyykJNx67fSy4 X-Received: by 2002:a17:906:c150:b0:745:f66d:a63c with SMTP id dp16-20020a170906c15000b00745f66da63cmr13817886ejc.761.1662361265807; Mon, 05 Sep 2022 00:01:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662361265; cv=none; d=google.com; s=arc-20160816; b=VEP72DzPWdPk01gDIwoFTfBLmDk+UBAsWR7BzOdYrKn7hlCqfT1vRAbkA8tEztQQu0 ML7BrSM+E7v4/HzRPa9+mfjude2tqJghnriYhAh1l1nMPJK14dDDXDCLMWVf9wMDnWYf 7GnrqFFQ1wXQEv7kInRkAUadI12GFwBRUzqOe261gtrsi16nsuQ27oIVwMUTwn73sAxz VJLYnpETYDgVfCPH3TlIVA4gIV0OJnifO6X2hcPrnO2c8D2I95Wk27Z/JbZbhA8P+R2T KEWrbSUl5simnSlezupcWV/fAgusvbmLOFXHYbB+5B2aYFOtiUiWyWYheSi6AGGQ3TJx G8RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=3OTxH04tly8ykdh4ItSLPlbz4yOOpq5wfxksyfOj0sA=; b=OsjE/8adi9CPdWlf6ZOrj/Tg6k8hCycbyJA7wJdRd26WfYViwRmhU1FOr7ps0u6+fn RzlXTscvblVcjSal/a7GHZ0t5YwvZSeBaUvK6lmjq1YTRkUFhCDqlfZcEqBUl7az/dBl URafPIX+j2SmsU604AkxzzQkZWvf5zYp9hRa9lkaZc8Exgz8Ro7OUpQDZGR5QsgLWHzD bY3KnkTcGYCBF41zTt0+4PnFxNSIOUs+j1E/DIsTNz/xfV8JLRlyvBi3vos0haaivUtY eyQWvsMhVcppFje67R46oTZc88hWSV+kOh3CMD+rkg9VnzjEtZSqKhpDWQlS7sHrQoLP bEAQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@canonical.com header.s=20210705 header.b="uGW1LI/e"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=canonical.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i23-20020a056402055700b0044e987f3a34si753001edx.489.2022.09.05.00.00.38; Mon, 05 Sep 2022 00:01:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@canonical.com header.s=20210705 header.b="uGW1LI/e"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=canonical.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234712AbiIEG4v (ORCPT + 99 others); Mon, 5 Sep 2022 02:56:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236822AbiIEG4i (ORCPT ); Mon, 5 Sep 2022 02:56:38 -0400 Received: from smtp-relay-canonical-1.canonical.com (smtp-relay-canonical-1.canonical.com [185.125.188.121]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0DA220F47; Sun, 4 Sep 2022 23:56:32 -0700 (PDT) Received: from HP-EliteBook-840-G7.. (1-171-245-2.dynamic-ip.hinet.net [1.171.245.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-1.canonical.com (Postfix) with ESMTPSA id DF2C93F3B3; Mon, 5 Sep 2022 06:56:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1662360990; bh=3OTxH04tly8ykdh4ItSLPlbz4yOOpq5wfxksyfOj0sA=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=uGW1LI/emstwM+wyRNi345Bi6KinpHcmTHeidzg/TU+4g1+LOGJ1bqORO4qnq8DMx D/UuNRRHw6jnyqDfhYh4tAbGsyyhez3/G05fUciVD5Lpz0sThwqGI5o6jRs9jQQppa a1wRG7GZSVNuq2v/ZG6lWIGXuMmGRWD9zXhx8eN6nlVL6SGI6IMOHw+E6RzIIY/bOK fuEHz/0qsLgKN2iuCxFrbxu+orqUyFWQaFnDaeSWy9G0czDODpnWvz19sPzs1prs/j DbleJTrJ/Z5Heve1deqnUrFnYAgPWD1Q9pA8yhWuOnnBi0SNq9E4pQinHYGuqGWiIC JPH1V9IA/2URQ== From: Kai-Heng Feng To: mika.westerberg@linux.intel.com, andreas.noever@gmail.com, michael.jamet@intel.com, YehezkelShB@gmail.com Cc: sanju.mehta@amd.com, mario.limonciello@amd.com, Kai-Heng Feng , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] thunderbolt: Resume PCIe bridges after switch is found on AMD USB4 controller Date: Mon, 5 Sep 2022 14:56:22 +0800 Message-Id: <20220905065622.1573811-1-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org AMD USB4 can not detect external PCIe devices like external NVMe when it's hotplugged, because card/link are not up: pcieport 0000:00:04.1: pciehp: pciehp_check_link_active: lnk_status = 1101 Use `lspci` to resume pciehp bridges can find external devices. A long delay before checking card/link presence doesn't help, either. The only way to make the hotplug work is to enable pciehp interrupt and check card presence after the TB switch is added. Since the topology of USB4 and its PCIe bridges are siblings, hardcode the bridge ID so TBT driver can wake them up to check presence. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=216448 Signed-off-by: Kai-Heng Feng --- drivers/thunderbolt/nhi.c | 29 +++++++++++++++++++++++++++++ drivers/thunderbolt/switch.c | 6 ++++++ drivers/thunderbolt/tb.c | 1 + drivers/thunderbolt/tb.h | 5 +++++ include/linux/thunderbolt.h | 1 + 5 files changed, 42 insertions(+) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index cb8c9c4ae93a2..75f5ce5e22978 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -1225,6 +1225,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tb_nhi *nhi; struct tb *tb; + struct pci_dev *p = NULL; + struct tb_pci_bridge *pci_bridge, *n; int res; if (!nhi_imr_valid(pdev)) { @@ -1306,6 +1308,19 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) nhi_shutdown(nhi); return res; } + + if (pdev->vendor == PCI_VENDOR_ID_AMD) { + while ((p = pci_get_device(PCI_VENDOR_ID_AMD, 0x14cd, p))) { + pci_bridge = kmalloc(sizeof(struct tb_pci_bridge), GFP_KERNEL); + if (!pci_bridge) + goto cleanup; + + pci_bridge->bridge = p; + INIT_LIST_HEAD(&pci_bridge->list); + list_add(&pci_bridge->list, &tb->bridge_list); + } + } + pci_set_drvdata(pdev, tb); device_wakeup_enable(&pdev->dev); @@ -1316,12 +1331,26 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) pm_runtime_put_autosuspend(&pdev->dev); return 0; + +cleanup: + list_for_each_entry_safe(pci_bridge, n, &tb->bridge_list, list) { + list_del(&pci_bridge->list); + kfree(pci_bridge); + } + + return -ENOMEM; } static void nhi_remove(struct pci_dev *pdev) { struct tb *tb = pci_get_drvdata(pdev); struct tb_nhi *nhi = tb->nhi; + struct tb_pci_bridge *pci_bridge, *n; + + list_for_each_entry_safe(pci_bridge, n, &tb->bridge_list, list) { + list_del(&pci_bridge->list); + kfree(pci_bridge); + } pm_runtime_get_sync(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index c63c1f4ff9dc7..aae898cc907d3 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2836,6 +2836,8 @@ static void tb_switch_credits_init(struct tb_switch *sw) int tb_switch_add(struct tb_switch *sw) { int i, ret; + struct tb *tb = sw->tb; + struct tb_pci_bridge *pci_bridge; /* * Initialize DMA control port now before we read DROM. Recent @@ -2933,6 +2935,10 @@ int tb_switch_add(struct tb_switch *sw) } tb_switch_debugfs_init(sw); + + list_for_each_entry(pci_bridge, &tb->bridge_list, list) + pm_request_resume(&pci_bridge->bridge->dev); + return 0; err_ports: diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 9853f6c7e81d7..07e97b77ac630 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1771,6 +1771,7 @@ struct tb *tb_probe(struct tb_nhi *nhi) tb->security_level = TB_SECURITY_NOPCIE; tb->cm_ops = &tb_cm_ops; + INIT_LIST_HEAD(&tb->bridge_list); tcm = tb_priv(tb); INIT_LIST_HEAD(&tcm->tunnel_list); diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 5db76de40cc1c..8efbd1afacad0 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -489,6 +489,11 @@ struct tb_cm_ops { u32 *status); }; +struct tb_pci_bridge { + struct pci_dev *bridge; + struct list_head list; +}; + static inline void *tb_priv(struct tb *tb) { return (void *)tb->privdata; diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 9f442d73f3df8..728bb36070e9d 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -83,6 +83,7 @@ struct tb { int index; enum tb_security_level security_level; size_t nboot_acl; + struct list_head bridge_list; unsigned long privdata[]; }; -- 2.36.1