• Mika Westerberg's avatar
    ACPI / hotplug / PCI: Don't scan bridges managed by native hotplug · 84c8b58e
    Mika Westerberg authored
    When acpiphp re-enumerates a PCI hierarchy because of an ACPI Notify()
    event, we should skip bridges managed by native hotplug (pciehp or shpchp).
    We don't want to scan below a native hotplug bridge until the hotplug
    controller generates a hot-add event.
    
    A typical scenario is a Root Port leading to a Thunderbolt host router that
    remains powered off until something is connected to it.  See [1] for the
    lspci details.
    
      1. Before something is connected, only the Root Port exists.  It has
         PCI_EXP_SLTCAP_HPC set and pciehp is responsible for hotplug:
    
           00:1b.0 Root Port (HotPlug+)
    
      2. When a USB-C or Thunderbolt device is connected, the Switch in the
         Thunderbolt host router is powered up, the Root Port signals a hotplug
         add event and pciehp enumerates the Switch:
    
           01:00.0 Switch Upstream Port   to [bus 02-39]
           02:00.0 Switch Downstream Port to [bus 03]    (HotPlug-, to NHI)
           02:01.0 Switch Downstream Port to [bus 04-38] (HotPlug+, to Thunderbolt connector)
           02:02.0 Switch Downstream Port to [bus 39]    (HotPlug-, to xHCI)
    
         The 02:00.0 and 02:02.0 Ports lead to Endpoints that are not powered
         up yet.  The Ports have PCI_EXP_SLTCAP_HPC cleared, so pciehp doesn't
         handle hotplug for them and we assign minimal resources to them.
    
         The 02:01.0 Port has PCI_EXP_SLTCAP_HPC set, so pciehp handles native
         hotplug events for it.
    
      3. The BIOS powers up the xHCI controller.  If a Thunderbolt device was
         connected (not just a USB-C device), it also powers up the NHI.  Then
         it sends an ACPI Notify() to the Root Port, and acpiphp enumerates the
         new device(s):
    
           03:00.0 Thunderbolt Host Controller (NHI) Endpoint
           39:00.0 xHCI Endpoint
    
      4. If a Thunderbolt device was connected, the host router firmware uses
         the NHI to set up Thunderbolt tunnels and triggers a native hotplug
         event (via 02:01.0 in this example).  Then pciehp enumerates the new
         Thunderbolt devices:
    
           04:00.0 Switch Upstream Port   to [bus 05-38]
           05:01.0 Switch Downstream Port to [bus 06-09] (HotPlug-)
           05:04.0 Switch Downstream Port to [bus 0a-38] (HotPlug+)
    
         In this example, 05:01.0 leads to another Switch and some NICs.  This
         subtree is static, so 05:01.0 doesn't support hotplug and has
         PCI_EXP_SLTCAP_HPC cleared.
    
    In step 3, acpiphp previously enumerated everything below the Root Port,
    including things below the 02:01.0 Port.  We don't want that because pciehp
    expects to manage hotplug below that Port, and firmware on the host router
    may be in the middle of configuring its Link so it may not be ready yet.
    
    To make this work better with the native PCIe (pciehp) and standard PCI
    (shpchp) hotplug drivers, we let them handle all slot management and
    resource allocation for hotplug bridges and restrict ACPI hotplug to
    non-hotplug bridges.
    
    [1] https://bugzilla.kernel.org/show_bug.cgi?id=199581#c5
    Link: https://lkml.kernel.org/r/20180529160155.1738-1-mika.westerberg@linux.intel.comSigned-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    [bhelgaas: changelog, use hotplug_is_native() instead of
    dev->is_hotplug_bridge]
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Reviewed-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    84c8b58e
acpiphp_glue.c 25.7 KB