06 Dec, 2011

1 commit

  • Right now we forcibly clear ASPM state on all devices if the BIOS indicates
    that the feature isn't supported. Based on the Microsoft presentation
    "PCI Express In Depth for Windows Vista and Beyond", I'm starting to think
    that this may be an error. The implication is that unless the platform
    grants full control via _OSC, Windows will not touch any PCIe features -
    including ASPM. In that case clearing ASPM state would be an error unless
    the platform has granted us that control.

    This patch reworks the ASPM disabling code such that the actual clearing
    of state is triggered by a successful handoff of PCIe control to the OS.
    The general ASPM code undergoes some changes in order to ensure that the
    ability to clear the bits isn't overridden by ASPM having already been
    disabled. Further, this theoretically now allows for situations where
    only a subset of PCIe roots hand over control, leaving the others in the
    BIOS state.

    It's difficult to know for sure that this is the right thing to do -
    there's zero public documentation on the interaction between all of these
    components. But enough vendors enable ASPM on platforms and then set this
    bit that it seems likely that they're expecting the OS to leave them alone.

    Measured to save around 5W on an idle Thinkpad X220.

    Signed-off-by: Matthew Garrett
    Signed-off-by: Jesse Barnes

    Matthew Garrett
     

22 May, 2011

1 commit

  • Need to use it in _e1000e_disable_aspm. This routine is used for error
    recovery, where the pci_bus_sem is already held, and we don't want
    pci_disable_link_state to try to take it again. So add a locked variant
    for use in cases like this.

    Found lock up:

    [ 2374.654557] kworker/32:1 D ffff881027f6b0f0 0 6075 2 0x00000000
    [ 2374.654816] ffff88503f099a68 0000000000000046 ffff88503f098000 0000000000004000
    [ 2374.654837] 00000000001d1ec0 ffff88503f099fd8 00000000001d1ec0 ffff88503f099fd8
    [ 2374.654860] 0000000000004000 00000000001d1ec0 ffff88503dcc8000 ffff88503f090000
    [ 2374.654880] Call Trace:
    [ 2374.654898] [] ? __lock_acquired+0x3a/0x224
    [ 2374.654914] [] ? _raw_spin_unlock_irq+0x30/0x36
    [ 2374.654925] [] ? trace_hardirqs_on_caller+0x1f/0x178
    [ 2374.654936] [] rwsem_down_failed_common+0xd3/0x103
    [ 2374.654945] [] ? __lock_contended+0x3a/0x2a2
    [ 2374.654955] [] rwsem_down_read_failed+0x12/0x14
    [ 2374.654967] [] call_rwsem_down_read_failed+0x14/0x30
    [ 2374.654981] [] ? pci_disable_link_state+0x5f/0xf5
    [ 2374.654990] [] ? down_read+0x7e/0x91
    [ 2374.654999] [] ? pci_disable_link_state+0x5f/0xf5
    [ 2374.655008] [] pci_disable_link_state+0x5f/0xf5
    [ 2374.655024] [] e1000e_disable_aspm+0x55/0x5a
    [ 2374.655037] [] e1000_io_slot_reset+0x59/0xea
    [ 2374.655048] [] ? report_mmio_enabled+0x5d/0x5d
    [ 2374.655057] [] report_slot_reset+0x2e/0x5d
    [ 2374.655072] [] pci_walk_bus+0x8a/0xb7
    [ 2374.655081] [] ? report_mmio_enabled+0x5d/0x5d
    [ 2374.655091] [] broadcast_error_message+0xa4/0xb2
    [ 2374.655101] [] ? pci_bus_read_config_dword+0x72/0x80
    [ 2374.655110] [] do_recovery+0x9e/0xf9
    [ 2374.655120] [] handle_error_source+0x4c/0x51
    [ 2374.655129] [] aer_isr_one_error+0x1e9/0x21a
    [ 2374.655138] [] aer_isr+0xc7/0xcc
    [ 2374.655147] [] ? aer_isr_one_error+0x21a/0x21a
    [ 2374.655159] [] process_one_work+0x237/0x3ec
    [ 2374.655168] [] ? process_one_work+0x1a8/0x3ec
    [ 2374.655178] [] worker_thread+0x17c/0x240
    [ 2374.655186] [] ? trace_hardirqs_on+0xd/0xf
    [ 2374.655196] [] ? manage_workers+0xab/0xab
    [ 2374.655209] [] kthread+0xa0/0xa8
    [ 2374.655223] [] kernel_thread_helper+0x4/0x10
    [ 2374.655232] [] ? retint_restore_args+0xe/0xe
    [ 2374.655243] [] ? __init_kthread_worker+0x5b/0x5b
    [ 2374.655252] [] ? gs_change+0xb/0xb

    when aer happens,
    pci_walk_bus already have down_read(&pci_bus_sem)...
    then report_slot_reset
    ==> e1000_io_slot_reset
    ==> e1000e_disable_aspm
    ==> pci_disable_link_state...

    We can not use pci_disable_link_state, and it will try to hold pci_bus_sem again.

    Try to have __pci_disable_link_state that will not need to hold pci_bus_sem.

    -v2: change name to pci_disable_link_state_locked() according to Jesse.

    [jbarnes: make sure new function is exported for modules]

    Signed-off-by: Yinghai Lu
    Signed-off-by: Jesse Barnes

    Yinghai Lu
     

22 Mar, 2011

1 commit

  • v3 -> v2: Moved ASPM enabling logic to pci_set_power_state()
    v2 -> v1: Preserved the logic in pci_raw_set_power_state()
    : Added ASPM enabling logic after scanning Root Bridge
    : http://marc.info/?l=linux-pci&m=130046996216391&w=2
    v1 : http://marc.info/?l=linux-pci&m=130013164703283&w=2

    The assumption made in commit 41cd766b065970ff6f6c89dd1cf55fa706c84a3d
    (PCI: Don't enable aspm before drivers have had a chance to veto it) that
    pci_enable_device() will result in re-configuring ASPM when aspm_policy is
    POWERSAVE is no longer valid. This is due to commit
    97c145f7c87453cec90e91238fba5fe2c1561b32 (PCI: read current power state
    at enable time) which resets dev->current_state to D0. Due to this the
    call to pcie_aspm_pm_state_change() is never made. Note the equality check
    (below) that returns early:
    ./drivers/pci/pci.c: pci_raw_set_pci_power_state()
    546 /* Check if we're already there */
    547 if (dev->current_state == state)
    548 return 0;

    Therefore OSPM never configures the PCIe links for ASPM to turn them "on".

    Fix it by configuring ASPM from the pci_enable_device() code path. This
    also allows a driver such as the e1000e networking driver a chance to
    disable ASPM (L0s, L1), if need be, prior to enabling the device. A
    driver may perform this action if the device is known to mis-behave
    wrt ASPM.

    Signed-off-by: Naga Chumbalkar
    Acked-by: Rafael J. Wysocki
    Cc: Matthew Garrett
    Signed-off-by: Jesse Barnes

    Naga Chumbalkar
     

24 Dec, 2010

1 commit

  • We currently refuse to touch the ASPM registers if the BIOS tells us that
    ASPM isn't supported. This can cause problems if the BIOS has (for any
    reason) enabled ASPM on some devices anyway. Change the code such that we
    explicitly clear ASPM if the FADT indicates that ASPM isn't supported,
    and make sure we tidy up appropriately on device removal in order to deal
    with the hotplug case. If ASPM is disabled because the BIOS doesn't hand
    over control then we won't touch the registers.

    Signed-off-by: Matthew Garrett
    Signed-off-by: Jesse Barnes

    Matthew Garrett
     

29 Jul, 2008

1 commit

  • The ACPI FADT table includes an ASPM control bit. If the bit is set, do
    not enable ASPM since it may indicate that the platform doesn't actually
    support the feature.

    Tested-by: Jack Howarth
    Signed-off-by: Shaohua Li
    Signed-off-by: Jesse Barnes

    Shaohua Li
     

21 Apr, 2008

1 commit

  • PCI Express ASPM defines a protocol for PCI Express components in the D0
    state to reduce Link power by placing their Links into a low power state
    and instructing the other end of the Link to do likewise. This
    capability allows hardware-autonomous, dynamic Link power reduction
    beyond what is achievable by software-only controlled power management.
    However, The device should be configured by software appropriately.
    Enabling ASPM will save power, but will introduce device latency.

    This patch adds ASPM support in Linux. It introduces a global policy for
    ASPM, a sysfs file /sys/module/pcie_aspm/parameters/policy can control
    it. The interface can be used as a boot option too. Currently we have
    below setting:
    -default, BIOS default setting
    -powersave, highest power saving mode, enable all available ASPM
    state and clock power management
    -performance, highest performance, disable ASPM and clock power
    management
    By default, the 'default' policy is used currently.

    In my test, power difference between powersave mode and performance mode
    is about 1.3w in a system with 3 PCIE links.

    Note: some devices might not work well with aspm, either because chipset
    issue or device issue. The patch provide API (pci_disable_link_state),
    driver can disable ASPM for specific device.

    Signed-off-by: Shaohua Li
    Signed-off-by: Greg Kroah-Hartman

    Shaohua Li