Skip to content

Commit 2b9941e

Browse files
committed
PCI / thunderbolt: Switch to use device links instead of PCI quirk
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. Signed-off-by: Mika Westerberg <[email protected]> Acked-by: Bjorn Helgaas <[email protected]>
1 parent b2911a5 commit 2b9941e

File tree

2 files changed

+66
-57
lines changed

2 files changed

+66
-57
lines changed

drivers/pci/quirks.c

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3673,63 +3673,6 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
36733673
DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
36743674
PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
36753675
quirk_apple_poweroff_thunderbolt);
3676-
3677-
/*
3678-
* Apple: Wait for the Thunderbolt controller to reestablish PCI tunnels
3679-
*
3680-
* During suspend the Thunderbolt controller is reset and all PCI
3681-
* tunnels are lost. The NHI driver will try to reestablish all tunnels
3682-
* during resume. We have to manually wait for the NHI since there is
3683-
* no parent child relationship between the NHI and the tunneled
3684-
* bridges.
3685-
*/
3686-
static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
3687-
{
3688-
struct pci_dev *sibling = NULL;
3689-
struct pci_dev *nhi = NULL;
3690-
3691-
if (!x86_apple_machine)
3692-
return;
3693-
if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
3694-
return;
3695-
3696-
/*
3697-
* Find the NHI and confirm that we are a bridge on the Thunderbolt
3698-
* host controller and not on a Thunderbolt endpoint.
3699-
*/
3700-
sibling = pci_get_slot(dev->bus, 0x0);
3701-
if (sibling == dev)
3702-
goto out; /* we are the downstream bridge to the NHI */
3703-
if (!sibling || !sibling->subordinate)
3704-
goto out;
3705-
nhi = pci_get_slot(sibling->subordinate, 0x0);
3706-
if (!nhi)
3707-
goto out;
3708-
if (nhi->vendor != PCI_VENDOR_ID_INTEL
3709-
|| (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
3710-
nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
3711-
nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI &&
3712-
nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
3713-
|| nhi->class != PCI_CLASS_SYSTEM_OTHER << 8)
3714-
goto out;
3715-
pci_info(dev, "quirk: waiting for Thunderbolt to reestablish PCI tunnels...\n");
3716-
device_pm_wait_for_dev(&dev->dev, &nhi->dev);
3717-
out:
3718-
pci_dev_put(nhi);
3719-
pci_dev_put(sibling);
3720-
}
3721-
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3722-
PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
3723-
quirk_apple_wait_for_thunderbolt);
3724-
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3725-
PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
3726-
quirk_apple_wait_for_thunderbolt);
3727-
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3728-
PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
3729-
quirk_apple_wait_for_thunderbolt);
3730-
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3731-
PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
3732-
quirk_apple_wait_for_thunderbolt);
37333676
#endif
37343677

37353678
/*

drivers/thunderbolt/nhi.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/module.h>
1818
#include <linux/delay.h>
1919
#include <linux/property.h>
20+
#include <linux/platform_data/x86/apple.h>
2021

2122
#include "nhi.h"
2223
#include "nhi_regs.h"
@@ -1069,6 +1070,69 @@ static bool nhi_imr_valid(struct pci_dev *pdev)
10691070
return true;
10701071
}
10711072

1073+
/*
1074+
* During suspend the Thunderbolt controller is reset and all PCIe
1075+
* tunnels are lost. The NHI driver will try to reestablish all tunnels
1076+
* during resume. This adds device links between the tunneled PCIe
1077+
* downstream ports and the NHI so that the device core will make sure
1078+
* NHI is resumed first before the rest.
1079+
*/
1080+
static void tb_apple_add_links(struct tb_nhi *nhi)
1081+
{
1082+
struct pci_dev *upstream, *pdev;
1083+
1084+
if (!x86_apple_machine)
1085+
return;
1086+
1087+
switch (nhi->pdev->device) {
1088+
case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE:
1089+
case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C:
1090+
case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI:
1091+
case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI:
1092+
break;
1093+
default:
1094+
return;
1095+
}
1096+
1097+
upstream = pci_upstream_bridge(nhi->pdev);
1098+
while (upstream) {
1099+
if (!pci_is_pcie(upstream))
1100+
return;
1101+
if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM)
1102+
break;
1103+
upstream = pci_upstream_bridge(upstream);
1104+
}
1105+
1106+
if (!upstream)
1107+
return;
1108+
1109+
/*
1110+
* For each hotplug downstream port, create add device link
1111+
* back to NHI so that PCIe tunnels can be re-established after
1112+
* sleep.
1113+
*/
1114+
for_each_pci_bridge(pdev, upstream->subordinate) {
1115+
const struct device_link *link;
1116+
1117+
if (!pci_is_pcie(pdev))
1118+
continue;
1119+
if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM ||
1120+
!pdev->is_hotplug_bridge)
1121+
continue;
1122+
1123+
link = device_link_add(&pdev->dev, &nhi->pdev->dev,
1124+
DL_FLAG_AUTOREMOVE_SUPPLIER |
1125+
DL_FLAG_PM_RUNTIME);
1126+
if (link) {
1127+
dev_dbg(&nhi->pdev->dev, "created link from %s\n",
1128+
dev_name(&pdev->dev));
1129+
} else {
1130+
dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
1131+
dev_name(&pdev->dev));
1132+
}
1133+
}
1134+
}
1135+
10721136
static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
10731137
{
10741138
struct tb_nhi *nhi;
@@ -1134,6 +1198,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
11341198
return res;
11351199
}
11361200

1201+
tb_apple_add_links(nhi);
1202+
11371203
tb = icm_probe(nhi);
11381204
if (!tb)
11391205
tb = tb_probe(nhi);

0 commit comments

Comments
 (0)