• Lukas Wunner's avatar
    PCI: Speed up algorithm in pci_bridge_d3_update() · e8559b71
    Lukas Wunner authored
    After a device has been added, removed or had its D3cold attributes
    changed, we recheck whether its parent bridge may runtime suspend to D3hot
    with pci_bridge_d3_update().
    
    The most naive algorithm would be to iterate over the bridge's children and
    check if any of them are blocking D3.
    
    The function already tries to be a bit smarter than that by first checking
    the device that was changed.  If this device already blocks D3 on the
    bridge, then walking over all the other children can be skipped.  A
    drawback of this approach is that if the device is *not* blocking D3, it
    will be checked a second time by pci_walk_bus().  But that's cheap and is
    outweighed by the performance gain of potentially skipping pci_walk_bus()
    altogether.
    
    The algorithm can be optimized further by taking into account if D3 is
    currently allowed for the bridge, as shown in the following truth table:
    
    (a)  remove &&  bridge_d3:  D3 is currently allowed for the bridge and
                                removing one of its children won't change
                                that.  No action necessary.
    (b)  remove && !bridge_d3:  D3 may now be allowed for the bridge if the
                                removed child was the only one blocking it.
                                Check all its siblings to verify that.
    (c) !remove &&  bridge_d3:  D3 may now be disallowed but this can only
                                be caused by the added/changed child, not
                                any of its siblings.  Check only that single
                                device.
    (d) !remove && !bridge_d3:  D3 may now be allowed for the bridge if the
                                changed child was the only one blocking it.
                                Check all its siblings to verify that.
                                By checking beforehand if the changed child
                                is blocking D3, we may be able to skip
                                checking its siblings.
    
    Currently we do not special-case option (a) and in case of option (c) we
    gratuitously call pci_walk_bus().  Speed up the algorithm by adding these
    optimizations.  Reword the comments a bit in an attempt to improve clarity.
    
    No functional change intended.
    Tested-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Reviewed-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    e8559b71
pci.c 138 KB