Various drivers in the kernel use `is_thunderbolt` or `pci_is_thunderbolt_attached` to designate behaving differently from a device that is internally in the machine. This relies upon checks for a specific capability only set on Intel controllers.
Non-Intel USB4 designs should also match this designation so that they can be treated the same regardless of the host they're connected to.
As part of adding the generic USB4 controller code, it was realized that `is_thunderbolt` and `pcie_is_thunderbolt_attached` have been overloaded.
Instead migrate to using removable attribute from device core.
Changes from v1->v2: - Add Alex's tag to first patch - Move lack of command completion into a quirk (Lukas) - Drop `is_thunderbolt` attribute and `pci_is_thunderbolt_attached` and use device core removable attribute instead - Adjust all consumers of old attribute to use removable
Mario Limonciello (9): thunderbolt: move definition of PCI_CLASS_SERIAL_USB_USB4 PCI: Move `is_thunderbolt` check for lack of command completed to a quirk PCI: drop `is_thunderbolt` attribute PCI: mark USB4 devices as removable drm/amd: drop the use of `pci_is_thunderbolt_attached` drm/nouveau: drop the use of `pci_is_thunderbolt_attached` drm/radeon: drop the use of `pci_is_thunderbolt_attached` platform/x86: amd-gmux: drop the use of `pci_is_thunderbolt_attached` PCI: drop `pci_is_thunderbolt_attached`
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 2 +- drivers/gpu/drm/nouveau/nouveau_vga.c | 4 ++-- drivers/gpu/drm/radeon/radeon_device.c | 4 ++-- drivers/gpu/drm/radeon/radeon_kms.c | 2 +- drivers/pci/hotplug/pciehp_hpc.c | 6 +----- drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 21 ++++++++------------- drivers/pci/quirks.c | 17 +++++++++++++++++ drivers/platform/x86/apple-gmux.c | 2 +- drivers/thunderbolt/nhi.h | 2 -- include/linux/pci.h | 25 ++----------------------- include/linux/pci_ids.h | 1 + 13 files changed, 38 insertions(+), 52 deletions(-)
This PCI class definition of the USB4 device is currently located only in the thunderbolt driver.
It will be needed by a few other drivers for upcoming changes. Move it into the common include file.
Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/thunderbolt/nhi.h | 2 -- include/linux/pci_ids.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h index 69083aab2736..79e980b51f94 100644 --- a/drivers/thunderbolt/nhi.h +++ b/drivers/thunderbolt/nhi.h @@ -81,6 +81,4 @@ extern const struct tb_nhi_ops icl_nhi_ops; #define PCI_DEVICE_ID_INTEL_TGL_H_NHI0 0x9a1f #define PCI_DEVICE_ID_INTEL_TGL_H_NHI1 0x9a21
-#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340 - #endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index aad54c666407..61b161d914f0 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -116,6 +116,7 @@ #define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310 #define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320 #define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330 +#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340 #define PCI_CLASS_SERIAL_USB_DEVICE 0x0c03fe #define PCI_CLASS_SERIAL_FIBER 0x0c04 #define PCI_CLASS_SERIAL_SMBUS 0x0c05
On Thu, Feb 10, 2022 at 04:43:21PM -0600, Mario Limonciello wrote:
This PCI class definition of the USB4 device is currently located only in the thunderbolt driver.
It will be needed by a few other drivers for upcoming changes. Move it into the common include file.
Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com
Acked-by: Mika Westerberg mika.westerberg@linux.intel.com
The `is_thunderbolt` check is currently used to indicate the lack of command completed support for a number of older Thunderbolt devices.
This however is heavy handed and should have been done via a quirk. Move the affected devices outlined in commit 493fb50e958c ("PCI: pciehp: Assume NoCompl+ for Thunderbolt ports") into pci quirks.
Suggested-by: Lukas Wunner lukas@wunner.de Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/pci/hotplug/pciehp_hpc.c | 6 +----- drivers/pci/quirks.c | 17 +++++++++++++++++ include/linux/pci.h | 2 ++ 3 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1c1ebf3dad43..e4c42b24aba8 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -996,11 +996,7 @@ struct controller *pcie_init(struct pcie_device *dev) if (pdev->hotplug_user_indicators) slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP);
- /* - * We assume no Thunderbolt controllers support Command Complete events, - * but some controllers falsely claim they do. - */ - if (pdev->is_thunderbolt) + if (pdev->no_cmd_complete) slot_cap |= PCI_EXP_SLTCAP_NCCS;
ctrl->slot_cap = slot_cap; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d2dd6a6cda60..6d3c88edde00 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3675,6 +3675,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE, quirk_thunderbolt_hotplug_msi);
+static void quirk_thunderbolt_command_completed(struct pci_dev *pdev) +{ + pdev->no_cmd_complete = 1; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, + quirk_thunderbolt_command_completed); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE, + quirk_thunderbolt_command_completed); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK, + quirk_thunderbolt_command_completed); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, + quirk_thunderbolt_command_completed); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C, + quirk_thunderbolt_command_completed); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE, + quirk_thunderbolt_command_completed); + #ifdef CONFIG_ACPI /* * Apple: Shutdown Cactus Ridge Thunderbolt controller. diff --git a/include/linux/pci.h b/include/linux/pci.h index 8253a5413d7c..1e5b769e42fc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -443,6 +443,8 @@ struct pci_dev { unsigned int is_hotplug_bridge:1; unsigned int shpc_managed:1; /* SHPC owned by shpchp */ unsigned int is_thunderbolt:1; /* Thunderbolt controller */ + unsigned int no_cmd_complete:1; /* Lies about command completed events */ + /* * Devices marked being untrusted are the ones that can potentially * execute DMA attacks and similar. They are typically connected
The `is_thunderbolt` attribute is currently a dumping ground for a variety of things.
Instead use the driver core removable attribute to indicate the detail a device is attached to a thunderbolt or USB4 chain.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 20 +++++++------------- drivers/platform/x86/apple-gmux.c | 2 +- include/linux/pci.h | 5 ++--- 4 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9ecce435fb3f..1264984d5e6d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2955,7 +2955,7 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return true;
/* Even the oldest 2010 Thunderbolt controller supports D3. */ - if (bridge->is_thunderbolt) + if (dev_is_removable(&bridge->dev)) return true;
/* Platform might know better if the bridge supports D3 */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 17a969942d37..e41656cdd8f0 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1577,16 +1577,6 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev) pdev->is_hotplug_bridge = 1; }
-static void set_pcie_thunderbolt(struct pci_dev *dev) -{ - u16 vsec; - - /* Is the device part of a Thunderbolt controller? */ - vsec = pci_find_vsec_capability(dev, PCI_VENDOR_ID_INTEL, PCI_VSEC_ID_INTEL_TBT); - if (vsec) - dev->is_thunderbolt = 1; -} - static void set_pcie_untrusted(struct pci_dev *dev) { struct pci_dev *parent; @@ -1603,6 +1593,10 @@ static void set_pcie_untrusted(struct pci_dev *dev) static void pci_set_removable(struct pci_dev *dev) { struct pci_dev *parent = pci_upstream_bridge(dev); + u16 vsec; + + /* Is the device a Thunderbolt controller? */ + vsec = pci_find_vsec_capability(dev, PCI_VENDOR_ID_INTEL, PCI_VSEC_ID_INTEL_TBT);
/* * We (only) consider everything downstream from an external_facing @@ -1615,8 +1609,9 @@ static void pci_set_removable(struct pci_dev *dev) * accessible to user / may not be removed by end user, and thus not * exposed as "removable" to userspace. */ - if (parent && - (parent->external_facing || dev_is_removable(&parent->dev))) + if (vsec || + (parent && + (parent->external_facing || dev_is_removable(&parent->dev)))) dev_set_removable(&dev->dev, DEVICE_REMOVABLE); }
@@ -1860,7 +1855,6 @@ int pci_setup_device(struct pci_dev *dev) dev->cfg_size = pci_cfg_space_size(dev);
/* Need to have dev->cfg_size ready */ - set_pcie_thunderbolt(dev);
set_pcie_untrusted(dev);
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 57553f9b4d1d..04232fbc7d56 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -596,7 +596,7 @@ static int gmux_resume(struct device *dev)
static int is_thunderbolt(struct device *dev, void *data) { - return to_pci_dev(dev)->is_thunderbolt; + return pci_is_thunderbolt_attached(to_pci_dev(dev)); }
static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) diff --git a/include/linux/pci.h b/include/linux/pci.h index 1e5b769e42fc..d9719eb14654 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -442,7 +442,6 @@ struct pci_dev { unsigned int is_virtfn:1; unsigned int is_hotplug_bridge:1; unsigned int shpc_managed:1; /* SHPC owned by shpchp */ - unsigned int is_thunderbolt:1; /* Thunderbolt controller */ unsigned int no_cmd_complete:1; /* Lies about command completed events */
/* @@ -2447,11 +2446,11 @@ static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev) { struct pci_dev *parent = pdev;
- if (pdev->is_thunderbolt) + if (dev_is_removable(&pdev->dev)) return true;
while ((parent = pci_upstream_bridge(parent))) - if (parent->is_thunderbolt) + if (dev_is_removable(&parent->dev)) return true;
return false;
Hi Mario,
On Thu, Feb 10, 2022 at 04:43:23PM -0600, Mario Limonciello wrote:
The `is_thunderbolt` attribute is currently a dumping ground for a variety of things.
Instead use the driver core removable attribute to indicate the detail a device is attached to a thunderbolt or USB4 chain.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 20 +++++++------------- drivers/platform/x86/apple-gmux.c | 2 +- include/linux/pci.h | 5 ++--- 4 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9ecce435fb3f..1264984d5e6d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2955,7 +2955,7 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return true;
/* Even the oldest 2010 Thunderbolt controller supports D3. */
if (bridge->is_thunderbolt)
if (dev_is_removable(&bridge->dev))
For this, I'm not entirely sure this is what we want. The purpose of this check is to enable port power management of Apple systems with Intel Thunderbolt controller and therefore checking for "removable" here is kind of misleading IMHO.
I wonder if we could instead remove the check completely here and rely on the below:
if (platform_pci_bridge_d3(bridge)) return true;
and that would then look like:
static inline bool platform_pci_bridge_d3(struct pci_dev *dev) { if (pci_use_mid_pm()) return false;
if (acpi_pci_bridge_d3(dev)) return true;
if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3")) return true;
return false; }
and then make a quirk in quirks.c that adds the software node property for the Apple systems? Or something along those lines.
@Lukas, what do you think?
[Public]
-----Original Message----- From: Mika Westerberg mika.westerberg@linux.intel.com Sent: Friday, February 11, 2022 04:24 To: Limonciello, Mario Mario.Limonciello@amd.com Cc: Bjorn Helgaas bhelgaas@google.com; Andreas Noever andreas.noever@gmail.com; open list:PCI SUBSYSTEM <linux- pci@vger.kernel.org>; open list:THUNDERBOLT DRIVER <linux- usb@vger.kernel.org>; open list:RADEON and AMDGPU DRM DRIVERS <amd- gfx@lists.freedesktop.org>; open list:DRM DRIVERS <dri- devel@lists.freedesktop.org>; open list:DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS nouveau@lists.freedesktop.org; open list:X86 PLATFORM DRIVERS platform-driver-x86@vger.kernel.org; Michael Jamet michael.jamet@intel.com; Yehezkel Bernat YehezkelShB@gmail.com; Lukas Wunner lukas@wunner.de; Deucher, Alexander Alexander.Deucher@amd.com Subject: Re: [PATCH v2 3/9] PCI: drop `is_thunderbolt` attribute
Hi Mario,
On Thu, Feb 10, 2022 at 04:43:23PM -0600, Mario Limonciello wrote:
The `is_thunderbolt` attribute is currently a dumping ground for a variety of things.
Instead use the driver core removable attribute to indicate the detail a device is attached to a thunderbolt or USB4 chain.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 20 +++++++------------- drivers/platform/x86/apple-gmux.c | 2 +- include/linux/pci.h | 5 ++--- 4 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9ecce435fb3f..1264984d5e6d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2955,7 +2955,7 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return true;
/* Even the oldest 2010 Thunderbolt controller supports D3. */
if (bridge->is_thunderbolt)
if (dev_is_removable(&bridge->dev))
For this, I'm not entirely sure this is what we want. The purpose of this check is to enable port power management of Apple systems with Intel Thunderbolt controller and therefore checking for "removable" here is kind of misleading IMHO.
I wonder if we could instead remove the check completely here and rely on the below:
if (platform_pci_bridge_d3(bridge)) return true;
and that would then look like:
static inline bool platform_pci_bridge_d3(struct pci_dev *dev) { if (pci_use_mid_pm()) return false;
if (acpi_pci_bridge_d3(dev)) return true;
if (device_property_read_bool(&dev->dev, "HotPlugSupportInD3")) return true;
return false; }
and then make a quirk in quirks.c that adds the software node property for the Apple systems? Or something along those lines.
@Lukas, what do you think?
I took a stab at doing this for V3, but I'm unsure whether ALL of the TBT controllers in pci_ids.h have been used in Apple laptops, so it might be a bit wasteful of a quirk list. If there is a known list somewhere that is shorter than that, it may be possible to pare down. Lukas, if you can please look closely at patch 3 of v3.
On Fri, Feb 11, 2022 at 12:23:51PM +0200, Mika Westerberg wrote:
On Thu, Feb 10, 2022 at 04:43:23PM -0600, Mario Limonciello wrote:
@@ -2955,7 +2955,7 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return true;
/* Even the oldest 2010 Thunderbolt controller supports D3. */
if (bridge->is_thunderbolt)
if (dev_is_removable(&bridge->dev))
For this, I'm not entirely sure this is what we want. The purpose of this check is to enable port power management of Apple systems with Intel Thunderbolt controller and therefore checking for "removable" here is kind of misleading IMHO.
[...]
and then make a quirk in quirks.c that adds the software node property for the Apple systems? Or something along those lines.
Honestly, that feels wrong to me.
There are non-Apple products with Thunderbolt controllers, e.g. Supermicro X10SAT was a Xeon board with Redwood Ridge which was introduced in 2013. This was way before Microsoft came up with the HotPlugSupportInD3 property. It was also way before the 2015 BIOS cut-off date that we use to disable power management on older boards.
Still, we currently whitelist the Thunderbolt ports on that board for D3 because we know it works. What if products like this one use their own power management scheme and we'd cause a power regression if we needlessly disable D3 for them now?
Thanks,
Lukas
Hi,
On Sun, Feb 13, 2022 at 09:39:28AM +0100, Lukas Wunner wrote:
On Fri, Feb 11, 2022 at 12:23:51PM +0200, Mika Westerberg wrote:
On Thu, Feb 10, 2022 at 04:43:23PM -0600, Mario Limonciello wrote:
@@ -2955,7 +2955,7 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return true;
/* Even the oldest 2010 Thunderbolt controller supports D3. */
if (bridge->is_thunderbolt)
if (dev_is_removable(&bridge->dev))
For this, I'm not entirely sure this is what we want. The purpose of this check is to enable port power management of Apple systems with Intel Thunderbolt controller and therefore checking for "removable" here is kind of misleading IMHO.
[...]
and then make a quirk in quirks.c that adds the software node property for the Apple systems? Or something along those lines.
Honestly, that feels wrong to me.
There are non-Apple products with Thunderbolt controllers, e.g. Supermicro X10SAT was a Xeon board with Redwood Ridge which was introduced in 2013. This was way before Microsoft came up with the HotPlugSupportInD3 property. It was also way before the 2015 BIOS cut-off date that we use to disable power management on older boards.
Still, we currently whitelist the Thunderbolt ports on that board for D3 because we know it works. What if products like this one use their own power management scheme and we'd cause a power regression if we needlessly disable D3 for them now?
All the non-Apple Thunderbolt products before "HotPlugSupportInD3" use ACPI "assisted" hotplug which means all the PM is done in the BIOS. Essentially it means the controller is only present if there is anything connected and in that case it is always in D0. Unplugging the device makes the controller to be hot-removed (ACPI hotplug) too and that's the only way early Thunderbolt used to save energy.
USB4 class devices are also removable like Intel Thunderbolt devices.
Drivers of downstream devices use this information to declare functional differences in how the drivers perform by knowing that they are connected to an upstream TBT/USB4 port.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/pci/probe.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e41656cdd8f0..73673a83eb5e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1610,6 +1610,7 @@ static void pci_set_removable(struct pci_dev *dev) * exposed as "removable" to userspace. */ if (vsec || + dev->class == PCI_CLASS_SERIAL_USB_USB4 || (parent && (parent->external_facing || dev_is_removable(&parent->dev)))) dev_set_removable(&dev->dev, DEVICE_REMOVABLE);
On 2/11/22 6:43 AM, Mario Limonciello wrote:
USB4 class devices are also removable like Intel Thunderbolt devices.
Drivers of downstream devices use this information to declare functional differences in how the drivers perform by knowing that they are connected to an upstream TBT/USB4 port.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/pci/probe.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e41656cdd8f0..73673a83eb5e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1610,6 +1610,7 @@ static void pci_set_removable(struct pci_dev *dev) * exposed as "removable" to userspace. */ if (vsec ||
dev_set_removable(&dev->dev, DEVICE_REMOVABLE);dev->class == PCI_CLASS_SERIAL_USB_USB4 || (parent && (parent->external_facing || dev_is_removable(&parent->dev))))
Reviewed-by: Macpaul Lin macpaul.lin@mediatek.com
Thanks!
Regards, Macpaul Lin
Hi Mario,
On Thu, Feb 10, 2022 at 04:43:24PM -0600, Mario Limonciello wrote:
USB4 class devices are also removable like Intel Thunderbolt devices.
Drivers of downstream devices use this information to declare functional differences in how the drivers perform by knowing that they are connected to an upstream TBT/USB4 port.
This may not be covering the integrated controllers. For discrete, yes but if it is the PCIe root ports that start the PCIe topology (over the PCIe tunnels) this does not work.
For integrated we have the "usb4-host-interface" ACPI property that tells this for each port:
https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-r...
and for discrete there is the PCIe DVSEC that can be used (see the USB4 spec archive it includes the "USB4 DVSEC Version 1.0.pdf" that has more information). I would expect AMD controller (assuming it is discrete) implements this too.
So I'm proposing that we mark the devices that are below PCIe ports (root, downstream) that fall in the above categories as "removable". This is then not dependent on checking the USB4 controller and how it is setup in a particular system.
[Public]
-----Original Message----- From: Mika Westerberg mika.westerberg@linux.intel.com Sent: Friday, February 11, 2022 04:35 To: Limonciello, Mario Mario.Limonciello@amd.com Cc: Bjorn Helgaas bhelgaas@google.com; Andreas Noever andreas.noever@gmail.com; open list:PCI SUBSYSTEM <linux- pci@vger.kernel.org>; open list:THUNDERBOLT DRIVER <linux- usb@vger.kernel.org>; open list:RADEON and AMDGPU DRM DRIVERS <amd- gfx@lists.freedesktop.org>; open list:DRM DRIVERS <dri- devel@lists.freedesktop.org>; open list:DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS nouveau@lists.freedesktop.org; open list:X86 PLATFORM DRIVERS platform-driver-x86@vger.kernel.org; Michael Jamet michael.jamet@intel.com; Yehezkel Bernat YehezkelShB@gmail.com; Lukas Wunner lukas@wunner.de; Deucher, Alexander Alexander.Deucher@amd.com Subject: Re: [PATCH v2 4/9] PCI: mark USB4 devices as removable
Hi Mario,
On Thu, Feb 10, 2022 at 04:43:24PM -0600, Mario Limonciello wrote:
USB4 class devices are also removable like Intel Thunderbolt devices.
Drivers of downstream devices use this information to declare functional differences in how the drivers perform by knowing that they are connected to an upstream TBT/USB4 port.
This may not be covering the integrated controllers. For discrete, yes but if it is the PCIe root ports that start the PCIe topology (over the PCIe tunnels) this does not work.
For integrated we have the "usb4-host-interface" ACPI property that tells this for each port:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.mi crosoft.com%2Fen-us%2Fwindows-hardware%2Fdrivers%2Fpci%2Fdsd-for-pcie- root-ports%23mapping-native-protocols-pcie-displayport-tunneled-through- usb4-to-usb4-host- routers&data=04%7C01%7Cmario.limonciello%40amd.com%7C64e5b663f 97b40f4035a08d9ed4a3162%7C3dd8961fe4884e608e11a82d994e183d%7C0%7 C0%7C637801725176496963%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sd ata=7BvPgExVP8Upvi25EEbqH9TacFDZ4zpCEKOfoBJWcxs%3D&reserved=0
and for discrete there is the PCIe DVSEC that can be used (see the USB4 spec archive it includes the "USB4 DVSEC Version 1.0.pdf" that has more information). I would expect AMD controller (assuming it is discrete) implements this too.
So I'm proposing that we mark the devices that are below PCIe ports (root, downstream) that fall in the above categories as "removable". This is then not dependent on checking the USB4 controller and how it is setup in a particular system.
Thanks for all of the great suggestions! I've incorporated them in v3.
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 1ebb91db2274..6dbf5753b5be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -161,7 +161,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) (amdgpu_is_atpx_hybrid() || amdgpu_has_atpx_dgpu_power_cntl()) && ((flags & AMD_IS_APU) == 0) && - !pci_is_thunderbolt_attached(to_pci_dev(dev->dev))) + !dev_is_removable(&adev->pdev->dev)) flags |= AMD_IS_PX;
parent = pci_upstream_bridge(adev->pdev); diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c index ee7cab37dfd5..2c5d74d836f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c @@ -382,7 +382,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
- if (pci_is_thunderbolt_attached(adev->pdev)) + if (dev_is_removable(&adev->pdev->dev)) data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT; else data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
On 2/11/22 6:43 AM, Mario Limonciello wrote:
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 1ebb91db2274..6dbf5753b5be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -161,7 +161,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) (amdgpu_is_atpx_hybrid() || amdgpu_has_atpx_dgpu_power_cntl()) && ((flags & AMD_IS_APU) == 0) &&
!pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
!dev_is_removable(&adev->pdev->dev))
flags |= AMD_IS_PX;
parent = pci_upstream_bridge(adev->pdev);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c index ee7cab37dfd5..2c5d74d836f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c @@ -382,7 +382,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
if (pci_is_thunderbolt_attached(adev->pdev))
else data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;if (dev_is_removable(&adev->pdev->dev)) data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
Reviewed-by: Macpaul Lin macpaul.lin@mediatek.com
Thanks!
Regards, Macpaul Lin
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/nouveau/nouveau_vga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 60cd8c0463df..2c8008cb38e0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -97,7 +97,7 @@ nouveau_vga_init(struct nouveau_drm *drm) vga_client_register(pdev, nouveau_vga_set_decode);
/* don't register Thunderbolt eGPU with vga_switcheroo */ - if (pci_is_thunderbolt_attached(pdev)) + if (dev_is_removable(&pdev->dev)) return;
vga_switcheroo_register_client(pdev, &nouveau_switcheroo_ops, runtime); @@ -120,7 +120,7 @@ nouveau_vga_fini(struct nouveau_drm *drm)
vga_client_unregister(pdev);
- if (pci_is_thunderbolt_attached(pdev)) + if (dev_is_removable(&pdev->dev)) return;
vga_switcheroo_unregister_client(pdev);
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/radeon/radeon_device.c | 4 ++-- drivers/gpu/drm/radeon/radeon_kms.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4f0fbf667431..5117fce23b3f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1439,7 +1439,7 @@ int radeon_device_init(struct radeon_device *rdev,
if (rdev->flags & RADEON_IS_PX) runtime = true; - if (!pci_is_thunderbolt_attached(rdev->pdev)) + if (!dev_is_removable(&rdev->pdev->dev)) vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); if (runtime) @@ -1527,7 +1527,7 @@ void radeon_device_fini(struct radeon_device *rdev) /* evict vram memory */ radeon_bo_evict_vram(rdev); radeon_fini(rdev); - if (!pci_is_thunderbolt_attached(rdev->pdev)) + if (!dev_is_removable(&rdev->pdev->dev)) vga_switcheroo_unregister_client(rdev->pdev); if (rdev->flags & RADEON_IS_PX) vga_switcheroo_fini_domain_pm_ops(rdev->dev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 11ad210919c8..e01ee7a5cf5d 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -139,7 +139,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) if ((radeon_runtime_pm != 0) && radeon_has_atpx() && ((flags & RADEON_IS_IGP) == 0) && - !pci_is_thunderbolt_attached(pdev)) + !dev_is_removable(&pdev->dev)) flags |= RADEON_IS_PX;
/* radeon_device_init should report only fatal error
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 04232fbc7d56..ffac15b9befd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -596,7 +596,7 @@ static int gmux_resume(struct device *dev)
static int is_thunderbolt(struct device *dev, void *data) { - return pci_is_thunderbolt_attached(to_pci_dev(dev)); + return dev_is_removable(dev); }
static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
Hi,
On 2/10/22 23:43, Mario Limonciello wrote:
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
Thanks, this looks good to me. I assume that this whole series will be merged in one go through another tree (e.g. the PCI tree), so here is my ack for merging this patch through another tree:
Acked-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 04232fbc7d56..ffac15b9befd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -596,7 +596,7 @@ static int gmux_resume(struct device *dev)
static int is_thunderbolt(struct device *dev, void *data) {
- return pci_is_thunderbolt_attached(to_pci_dev(dev));
- return dev_is_removable(dev);
}
static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
On Fri, Feb 11, 2022 at 12:43 AM Mario Limonciello mario.limonciello@amd.com wrote:
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 04232fbc7d56..ffac15b9befd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -596,7 +596,7 @@ static int gmux_resume(struct device *dev)
static int is_thunderbolt(struct device *dev, void *data) {
return pci_is_thunderbolt_attached(to_pci_dev(dev));
return dev_is_removable(dev);
}
Maybe it's only me, but isn't it a bit strange to keep this function named `is_thunderbolt` while it's actually about being removable?
Hi,
On 2/11/22 10:00, Yehezkel Bernat wrote:
On Fri, Feb 11, 2022 at 12:43 AM Mario Limonciello mario.limonciello@amd.com wrote:
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
The PCI core now marks such devices as removable and downstream drivers can use this instead.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com
drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 04232fbc7d56..ffac15b9befd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -596,7 +596,7 @@ static int gmux_resume(struct device *dev)
static int is_thunderbolt(struct device *dev, void *data) {
return pci_is_thunderbolt_attached(to_pci_dev(dev));
return dev_is_removable(dev);
}
Maybe it's only me, but isn't it a bit strange to keep this function named `is_thunderbolt` while it's actually about being removable?
The comment above the only caller says:
/* * If Thunderbolt is present, the external DP port is not fully * switchable. Force its AUX channel to the discrete GPU. */ gmux_data->external_switchable = !bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt);
So IHMO keeping the name as is is fine.
Regards,
Hans
Currently `pci_is_thunderbolt_attached` is used to indicate a device is connected externally.
As all drivers now look at the removable attribute, drop this function.
Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- include/linux/pci.h | 22 ---------------------- 1 file changed, 22 deletions(-)
diff --git a/include/linux/pci.h b/include/linux/pci.h index d9719eb14654..089e7e36a0d9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2434,28 +2434,6 @@ static inline bool pci_ari_enabled(struct pci_bus *bus) return bus->self && bus->self->ari_enabled; }
-/** - * pci_is_thunderbolt_attached - whether device is on a Thunderbolt daisy chain - * @pdev: PCI device to check - * - * Walk upwards from @pdev and check for each encountered bridge if it's part - * of a Thunderbolt controller. Reaching the host bridge means @pdev is not - * Thunderbolt-attached. (But rather soldered to the mainboard usually.) - */ -static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev) -{ - struct pci_dev *parent = pdev; - - if (dev_is_removable(&pdev->dev)) - return true; - - while ((parent = pci_upstream_bridge(parent))) - if (dev_is_removable(&parent->dev)) - return true; - - return false; -} - #if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH) void pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type); #endif
dri-devel@lists.freedesktop.org