@@ -250,6 +250,125 @@ void __init pci_acpi_crs_quirks(void)
250250 pr_info ("Please notify linux-pci@vger.kernel.org so future kernels can do this automatically\n" );
251251}
252252
253+ /*
254+ * Check if pdev is part of a PCIe switch that is directly below the
255+ * specified bridge.
256+ */
257+ static bool pcie_switch_directly_under (struct pci_dev * bridge ,
258+ struct pci_dev * pdev )
259+ {
260+ struct pci_dev * parent = pci_upstream_bridge (pdev );
261+
262+ /* If the device doesn't have a parent, it's not under anything */
263+ if (!parent )
264+ return false;
265+
266+ /*
267+ * If the device has a PCIe type, check if it is below the
268+ * corresponding PCIe switch components (if applicable). Then check
269+ * if its upstream port is directly beneath the specified bridge.
270+ */
271+ switch (pci_pcie_type (pdev )) {
272+ case PCI_EXP_TYPE_UPSTREAM :
273+ return parent == bridge ;
274+
275+ case PCI_EXP_TYPE_DOWNSTREAM :
276+ if (pci_pcie_type (parent ) != PCI_EXP_TYPE_UPSTREAM )
277+ return false;
278+ parent = pci_upstream_bridge (parent );
279+ return parent == bridge ;
280+
281+ case PCI_EXP_TYPE_ENDPOINT :
282+ if (pci_pcie_type (parent ) != PCI_EXP_TYPE_DOWNSTREAM )
283+ return false;
284+ parent = pci_upstream_bridge (parent );
285+ if (!parent || pci_pcie_type (parent ) != PCI_EXP_TYPE_UPSTREAM )
286+ return false;
287+ parent = pci_upstream_bridge (parent );
288+ return parent == bridge ;
289+ }
290+
291+ return false;
292+ }
293+
294+ static bool pcie_has_usb4_host_interface (struct pci_dev * pdev )
295+ {
296+ struct fwnode_handle * fwnode ;
297+
298+ /*
299+ * For USB4, the tunneled PCIe Root or Downstream Ports are marked
300+ * with the "usb4-host-interface" ACPI property, so we look for
301+ * that first. This should cover most cases.
302+ */
303+ fwnode = fwnode_find_reference (dev_fwnode (& pdev -> dev ),
304+ "usb4-host-interface" , 0 );
305+ if (!IS_ERR (fwnode )) {
306+ fwnode_handle_put (fwnode );
307+ return true;
308+ }
309+
310+ /*
311+ * Any integrated Thunderbolt 3/4 PCIe Root Ports from Intel
312+ * before Alder Lake do not have the "usb4-host-interface"
313+ * property so we use their PCI IDs instead. All these are
314+ * tunneled. This list is not expected to grow.
315+ */
316+ if (pdev -> vendor == PCI_VENDOR_ID_INTEL ) {
317+ switch (pdev -> device ) {
318+ /* Ice Lake Thunderbolt 3 PCIe Root Ports */
319+ case 0x8a1d :
320+ case 0x8a1f :
321+ case 0x8a21 :
322+ case 0x8a23 :
323+ /* Tiger Lake-LP Thunderbolt 4 PCIe Root Ports */
324+ case 0x9a23 :
325+ case 0x9a25 :
326+ case 0x9a27 :
327+ case 0x9a29 :
328+ /* Tiger Lake-H Thunderbolt 4 PCIe Root Ports */
329+ case 0x9a2b :
330+ case 0x9a2d :
331+ case 0x9a2f :
332+ case 0x9a31 :
333+ return true;
334+ }
335+ }
336+
337+ return false;
338+ }
339+
340+ bool arch_pci_dev_is_removable (struct pci_dev * pdev )
341+ {
342+ struct pci_dev * parent , * root ;
343+
344+ /* pdev without a parent or Root Port is never tunneled */
345+ parent = pci_upstream_bridge (pdev );
346+ if (!parent )
347+ return false;
348+ root = pcie_find_root_port (pdev );
349+ if (!root )
350+ return false;
351+
352+ /* Internal PCIe devices are not tunneled */
353+ if (!root -> external_facing )
354+ return false;
355+
356+ /* Anything directly behind a "usb4-host-interface" is tunneled */
357+ if (pcie_has_usb4_host_interface (parent ))
358+ return true;
359+
360+ /*
361+ * Check if this is a discrete Thunderbolt/USB4 controller that is
362+ * directly behind the non-USB4 PCIe Root Port marked as
363+ * "ExternalFacingPort". Those are not behind a PCIe tunnel.
364+ */
365+ if (pcie_switch_directly_under (root , pdev ))
366+ return false;
367+
368+ /* PCIe devices after the discrete chip are tunneled */
369+ return true;
370+ }
371+
253372#ifdef CONFIG_PCI_MMCONFIG
254373static int check_segment (u16 seg , struct device * dev , char * estr )
255374{
0 commit comments